C 语言之const关键字

普通const只读变量

编译器不为普通的const只读变量分配存储空间,而是将它们保存在符号表中。不像#define一样在预编译过程中给出立即数,在预编译阶段进行替换,const修饰的只读变量在编译的时候确定其值。

const int a = 10;  //一般变量
const int arr[5] = {1,2,3,4,5}

修饰指针

例子

 const int *p;  		//p可变,p指向的对象不可变
 int const *p;  		//p可变,p指向的对象不可变
 int *const p;  		//p不可变,p指向的对象可变
 const int *const p; 	//指针p和指针p指向的对象都不可变  

记忆方法

先忽略类型名(编译器解析的时候也先忽略类型名),看const离哪个近,离谁近就修饰谁,修饰谁谁就不可变

  • const int *p;
    const 修饰 *p,p是指针,*p是指针指向的对象,不可变
  • int const *p;
    const 修饰 *p,p是指针,*p是指针指向的对象,不可变
  • int *const p;
    const修改p,p 是指针,p不可变,p指向的对象可变
  • const int * const p
    前一个const修饰*p,后一个const修饰p,都不可变

修饰函数的参数

const修饰符也可以修饰函数的参数,当不希望这个参数值在函数体内被意外修改时使用。

void Fun(const int *p);

告诉编译器,*p在函数体中不能改变,从而防止了使用者的一些无意的错误修改。
在C语言中,有很多库函数的形参被定义为const *类型

size_t strlen ( const char * str );
int strcmp ( const char * str1, const char * str2 );
char * strcat ( char * destination, const char * source );
char * strcpy ( char * destination, const char * source );
int printf ( const char * format, ... );

自定义的函数const限制

加const限制符表明,调用该函数不会修改传进来的对象的值。不但可以防止由于程序员误操作引起的字符串修改,还可以给用户一个提示,函数不会修改你提供的字符串。

#include <stdio.h>
//查找字符串中某个相同的字符
void my_fun(const char *str, char ch, int *num)
{
	int ch_sum = 0;
	while (*str != '\0')
	{
		if (*str++ == ch)
		{
			ch_sum ++;	
		}	
	}
	*num = ch_sum;
}

int main()
{
	const char *str = "adbacccsdddde";
	char ch = 'd';
	int n = 0;
	my_fun(str, ch, &n);
	printf("character d num is = %d\n", n);
	return 0;
}

修饰函数的返回值

const修饰符也可以修饰函数的返回值,返回值不可被改变。例如:

const int Fun(void);

const和非const的转换

在编写函数的过程中,经常会遇到编译器的warning,提示某个函数的入参是一个const char*类型,但是传入的指针却没带const。此时怎么办呢?

警告给出的场景

const char *str1 = "this is const string and can not be modified" //str1为指向字符串常量的指针

void my_fun(char *str2);
void my_fun(char *str2)
{
	... //处理str_data指向的字符串,此时,
	... //str_data指向的字符串可被修改,因为函数入参没有带const限制  
}
int main()
{
	my_fun(str1);
}
  • 在上述情况下,编译器会发出警告,因为通过str不能修改数据,而赋值后通过str2能够修改数据了,意义发生了转变,所以编译不提倡这种行为,会给出错误或警告。在VS2017下给出的警告如下:
void my_fun(char *str, char ch, int *num);
int main()
{
	const char *str = "adbacccsdddde";
	char ch = 'd';
	int n = 0;
	my_fun(str, ch, &n);
	printf("character d num is = %d\n", n);
	return 0;
}

warning C4090: “函数”: 不同的“const”限定符

const和非const char* 指向数据的降级与升级

  • 不能将const char *类型的数据赋给char *类型的变量。
  • 编译器允许将char 类型的数据赋值给const char类型的变量。 例子:
void my_fun(const char *str, char ch, int *num)
{
	...
}

int main()
{
	char *str = "adbacccsdddde";  //这里将之前的const 关键字去掉后,编译器未warning,程序正常运行
	char ch = 'd';
	int n = 0;
	my_fun(str, ch, &n);
	printf("character d num is = %d\n", n);
	return 0;
}

如何理解

  • char * 指向的数据有 “读”/==“写”==权限
  • const char*指向的数据只有 “读” 权限
  • 降低数据的权限不会带来风险,反之提升则有可能发生危险

const 和 数值宏常量

为了安全,建议在定义一些宏常数的时候用const代替,编译器会给const修饰的只读变量做类型校验,减少错误的可能。但一定要注意,const修饰的不是常量而是readonly的变量,const修饰的只读变量不能用来做为定义数组的维数,也不能放在case关键字后面。

#define  MAX_NUM	100

int data[MAX_NUM] = {0}; //可以编译

const int Max_Num = 100;
int data[Max_Num] ={0} //错误,因为const定义的只读变量不能定义数组的维数
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值