c语言之——const关键字

一、简介

(1)const关键字,在C语言中用来修饰变量,表示这个变量不可更改。

我们可能首先想到的是经过它修饰的变量便是常量了。其实我们这种想法是错误的,其实 const 修饰的变量是只读的,其本质还是变量。它只是告诉编译器该变量不能出现在赋值符号的左边。

那么,const修饰的变量真的不能修改吗?我么看如下代码

#include <stdio.h>

int main(void)
{
	const int a = 5;
	//a = 6;				// error: assignment of read-only variable ‘a’
	int *p;
	p = (int *)&a;			// 这里报警高可以通过强制类型转换来消除
	*p = 6;
	printf("a = %d.\n", a);	// a = 6,结果证明const类型的变量被改了
	return 0;
}
  • const修饰的变量其实是可以改的(前提是gcc环境下)。
  • 对于某些编译器,const修饰的变量是不可以改的。const修饰的变量到底能不能真的被修改,取决于具体的环境,C语言本身并没有完全严格一致的要求。
  • 在gcc中,const是通过编译器在编译的时候执行检查来确保实现的(也就是说const类型的变量不能改是编译错误,不是运行时错误。)所以我们只要想办法骗过编译器,就可以修改const定义的常量,而运行时不会报错。

对于const与编译器的关系详见如下文章:https://blog.51cto.com/12810168/2095264

图片.png

 

二、const关键字与指针

const修饰指针有4种形式,区分清楚这4种即可全部理解const和指针。

第一种:const int *p;

第二种:int const *p;

第三种:int * const p;

第四种:const int * const p;

关于指针变量的理解,主要涉及到2个变量:第一个是指针变量p本身,第二个是p指向的那个变量(*p)。一个const关键字只能修饰一个变量,所以弄清楚这4个表达式的关键就是搞清楚const放在某个位置是修饰谁的。

const后面要是直接跟着指针变量,就是修饰指针变量。例如 int * const p3;       // p本身是cosnt的,p指向的变量不是const的

  • 常量指针是指针指向的内容是常量;
  • 指针常量是指指针本身是个常量,不能在指向其他的地址;
  • 指向常量的常指针,以上两种的结合。
#include <stdio.h>

int main(void)
{
	int a = 5;
	
	// 第一种
	const int *p1;		// p本身不是cosnt的,而p指向的变量是const的
	// 第二种
	int const *p2;		// p本身不是cosnt的,而p指向的变量是const的
	
	
	// 第三种
	int * const p3;		// p本身是cosnt的,p指向的变量不是const的
	// 第四种
	const int * const p4;// p本身是cosnt的,p指向的变量也是const的
	
	*p1  = 3;		// error: assignment of read-only location ‘*p1’
	p1 = &a;		// 编译无错误无警告
	
	*p2 = 5;		// error: assignment of read-only location ‘*p2’
	p2 = &a;		// 编译无错误无警告
	
	*p3 = 5;		// 编译无错误无警告
	p3 = &a;		// error: assignment of read-only variable ‘p3’
	
	p4 = &a;		// error: assignment of read-only variable ‘p4’
	*p4 = 5;		// error: assignment of read-only location ‘*p4’

	return 0;
}

note:const与typedef结合使用时,需要注意:

(1)typedef int *PINT; const PINT p2; 相当于是int *const p2;

(2)typedef int *PINT; PINT const p2; 相当于是int *const p2;

(3)如果确实想得到const int *p;这种效果,只能typedef const int *CPINT; CPINT p1;

 

三、const关键字与函数形参

(1)const一般用在函数参数列表中,用法是const int *p;(意义是指针变量p本身可变的,而p所指向的变量是不可变的)。

(2)const用来修饰指针做函数传参,作用就在于声明在函数内部不会改变这个指针所指向的内容,所以给该函数传一个不可改变的指针(char *p = "linux";这种)不会触发错误;而一个未声明为const的指针的函数,你给他传一个不可更改的指针的时候就要小心了。

(3)编程中函数的输入和输出都是靠函数形参的,返回值只是用来表示函数执行的结果是对(成功)还是错(失败)。如果这个参数是用来做输入的,就叫输入型参数;如果这个参数的目的是用来做输出的,就叫输出型参数。(在典型的linux风格函数中,返回值是不用来返回结果的,而是用来返回0或者负数用来表示程序执行结果是对还是错,是成功还是失败)。

#include <stdio.h>

int multip5_3(int a, int *p);


int main(void)
{
	int a, b = 0, ret = -1;
	
	a = 30;
	ret = multip5_3(a, &b);
	if (ret == -1)
	{
		printf("出错了\n");
	}
	else
	{
		printf("result = %d.\n", b);
	}
	

	return 0;
}


int multip5_3(int a, int *p)
{
	int tmp;

	tmp = 5 * a;
	if (tmp > 100)
	{
		return -1;
	}
	else
	{
		*p = tmp;
		return 0;
	}
}

小结:

看到一个函数的原型后,怎么样一眼看出来哪个参数做输入哪个做输出?函数传参如果传的是普通变量(不是指针)那肯定是输入型参数;如果传指针就有2种可能性了,为了区别,经常的做法是:如果这个参数是做输入的(通常做输入的在函数内部只需要读取这个参数而不会需要更改它)就在指针前面加const来修饰;如果函数形参是指针变量并且还没加const,那么就表示这个参数是用来做输出型参数的。

譬如C库函数(#include <string.h> 和 #include <stdio.h>)中strcpy函数

char *strcpy(char* dest, const char *src);

REF:

https://blog.51cto.com/12810168/2095264

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值