C语言重要知识点总结(三)--const、volatile、extern、static、restrict、register关键字解析

一、const

C语言中关键字const用来定义一个常量,如果一个变量被const修饰,那么它的值就不能再改变,只能被读取。
(一)const修饰局部变量时**
const int num = 10;
int const num = 10;
上述两种对变量num的定义都是正确的,此时不能再重新给num赋值,num成为一个只读变量。如果强制给num重新赋值,会出现程序错误。
(二)const与指针
1.const int* p = &num
int const *p = &num
上面两种定义方法相同,const修饰的是一个int型的指针p,p中存放的是num的地址。因此p是一个常量指针。
常量指针指的是不能通过这个指针来改变变量的值,但是可以通过其他引用方式给变量重新赋值,并且此时的指针p也可以指向其他地址。

int main()
{
	int num = 10;
	n = 100;
	const int* p = #
	*p = 30;//程序报错
	num = 20;//重新赋值,num的值变为20
	p = &n;//将指针指向其他地址
	return 0;
}

2.int* const p = #
此时的指针p是一个指针常量,指的是指针本身是一个常量,因此指针不能再指向其他任何地址,但是p所指向的变量num的数值可以改变。

int main()
{
	int num = 10;
	int n = 20;
	int* const p = #
	num = 20;//修改成功
	printf("%d\n",num);
	*p = 30;//修改成功
	printf("%d\n",num);
    p = &n;//程序报错,左值指定 const 对象
	return 0;
}

区分常量指针和指针常量的关键就在于*的位置,如果const在*的左边,则为常量指针,如果const在*的右边则为指针常量。
3.const int* const p = &num
这是上面两种情况相结合的情况,此时,不能通过指针来修改num的值,也不能将指针指向其他地址,但是num可以通过别的引用方式更改。

int main()
{
	int num = 10;
	int n = 20;
	const int* const p = #
	num = 20;
	printf("%d\n",num);
	*p = 30;//程序报错,左值指定 const 对象
    p = &n;//程序报错,左值指定 const 对象
	return 0;
}

(三)const修饰函数的参数
const修饰函数的参数与const修饰局部变量的三种情况类似
(四)const修饰函数的返回值
如果函数返回值是一个指针,并且这个指针被const修饰,那么函数的返回值(即指针)的内容不能被修改,该返回值只能用加有const修饰的同类型指针来接收。
(五)const修饰全局变量
与修饰局变量的用法相同

二、volatile

volatile是一个类型限定词,用它来修饰一个变量时,它的作用是告诉编译器该变量除了被程序改变还有可能意外被的被其他程序改变,因此,每一次读取该变量都会从内存中读取,不会进行优化,不会从寄存器中读取备份。
例如:在多线程情况下,由于一个变量可以被任意一个线程修改,因此读取变量的值时,要确保每一次读取到的值都是最新的,该变量可以用volatile关键字来修饰。

三、extern

extern可以置于变量或者函数前,以标识该变量或者函数的定义在别的文件中,提示编译器看到此变量和函数时在其他模块中寻找定义,在使用extern时要严格对应声明的格式。

四、static

(一)static修饰局部变量
在任何一个函数内部定义的变量都都属于局部变量,编译器一般不会对普通的局部变量进行初始化,也就是说它的值在初始时不确定的。普通的局部变量位于栈上,在函数调用结束后会自动销毁。
局部变量被static修饰后,如果在定义时未对其进行赋值初始化,编译器会自动将其初始化为0。而且,静态局部变量存储在静态区,函数调用结束后,被static修饰的变量不会被销毁,值也不会改变。但是,静态局部变量的作用域是在函数内部,当函数结束后,它的作用域也会结束。

void funStatic()
{
	static int n = 1;
	n = n*2;
	printf("%d\n",n);
}
void fun()
{
	int n = 1;
	n = n*2;
	printf("%d\n",n);
}
int main()
{
	fun();//输出2
	fun();//输出2
	fun();//输出2
	funStatic();//输出2
	funStatic();//输出4
	funStatic();//输出8
	return 0;
}

(二)static修饰函数和全局变量
static修饰全局变量或函数时,不是为了限制其存储方式,而主要是为了限制该全局变量或函数的作用域仅限于本文件,所以又称为内部函数。此时,对于全局变量,不论是否有static限制,它的存储区域都是在静态存储区,声明周期都是全局的,此时的static只是限定作用域在本模块中。
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数是否与其他文件中的函数重名。

五、restrict

关键字restrict通过允许编译器优化某几种代码而增强了计算机支持。它只可用于指针,并且表明指针是访问这个数据对象的唯一初始方式。(这个关键字只是告诉编译器和用户某个变量只有唯一一个入口可改变它的值,但是却不会检查是否是一定只有一个)
可以将关键字restrict作为指针函数参数的限定词使用,这意味着编译器可以假定在函数体内没有其他标识符修改指针指向的数据,因而编译器会试着优化程序,提高 效率。

六、register

register关键字请求编译器尽可能的将变量存储在CPU的内部寄存器中,而不是通过内存寻址访问,以提高运行效率。
如果定义了过多的register变量或寄存器中存储的内容过多,超过了容量,编译器就不会将变量放入寄存器,所以是“尽可能”。
register使用注意:
1.修饰的变量必须是寄存器所能接受的类型
2.因为是尽可能放在寄存器里,不一定在内存里,因此不能用取地址运算符“&”来获取register变量的地址

C语言重要知识点总结(一)–编译链接过程、数据类型、操作符
C语言重要知识点总结(二)–内存结构、函数调用过程(栈帧)、宏的优缺点以及##和#的使用
C语言重要知识点总结(四)–结构体、结构体内存对齐、位段、枚举、联合
以上总结如有不足之处,希望指出,谢谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值