前言
本文用简单代码实验介绍register关键字的使用。
上代码
#include <stdio.h>
int main(void)
{
int i;
int tmp = 0;
for (i=1; i<5; i++) {
tmp++;
printf("tmp = %d\n", tmp);
printf("&i = %d\n\n", &i);
}
return 0;
}
/*
运行结果:
tmp = 1
&i = 6422296
tmp = 2
&i = 6422296
tmp = 3
&i = 6422296
tmp = 4
&i = 6422296
*/
改代码
#include <stdio.h>
int main(void)
{
/* 加上register关键字 */
register int i;
int tmp = 0;
for (i=1; i<5; i++) {
tmp++;
printf("tmp = %d\n", tmp);
printf("&i = %d\n\n", &i);
}
return 0;
}
/*
运行结果:
045.c: In function 'main':
045.c:16:3: error: address of register variable 'i' requested
16 | printf("&i = %d\n\n", &i);
*/
错误分析:
原因:address of register variable ‘i’ requested
问题
为什么register修饰的变量不能取地址呢?
学习
-
register关键字的作用
首先,register关键字会:
“advises the compiler that the variable in questions will be heavily used”如果advise成功,则:
“register variables are to be replaced in machine registers, which may result in smaller and faster programers”但是呢, “compilers are free to ignore the advise”
从上述内容中可知,register关键字也只能向编译器“提建议”,建议把它修饰的变量放入寄存器,但是否放入寄存器最终还是编译器说了算。
当然,“言论自由不代表可以散布谣言、扰乱社会治安”,所以: “the register declaration can only be applied to automatic variables and to formal parameters of a function”
那么,为什么register会有这么多限制呢?只能提建议,还要按规定提建议。 限制来源于“物理寄存器“本身的特点。
寄存器在cpu内部,特殊的位置使它存取数据速度最快,但是数量也最少。所以一定要省着点用,要注意及时回收。
程序员根本不知道程序运行的时候,cpu中有多少寄存器可以使用,所以是否放入寄存器还得编译器说的靠谱。 另外,寄存器这么珍贵的资源,当然不能被某些变量一直占着不释放,所以register只能用来修饰自动变量和形参这些一旦所在的子函数运行结束立即释放、占用寄存器周期短的变量。全局变量得等到整个程序运行结束才释放,若放入寄存器,就很可能造成寄存器使用完毕的情况,寄存器使用完,cpu就瘫痪了。
- &符号的用法
“the & operator only applies to objects in memory: variables and array elements”
看到这,也许有人觉得,取地址符号&只能应用于内存,register变量在寄存器中,当然不能对register变量取地址了。
别忘了,register只是建议,有的register修饰的变量被编译器放入了内存,那这个时候能不能取地址呢?
答案:规定了,不能。“it is not possible to take the address of a register variable, regardless of whether the variable is actually placed in a register”
大总结
- register修饰的变量由编译器决定是否放入寄存器
- 取地址符号只能应用于内存,求取内存中的地址,不能取寄存器的地址
- 就算register修饰的变量被编译器放到了内存,规定也不能使用取地址符号&求其地址,否则编译报错。
阅读摘抄分享:
木桶定律:
- 阿喀琉斯之踵,再刀枪不入与百毒不侵,也有最薄弱之处。
- 遇到问题,不要蛮干,找到导致问题的“短板”,科学予以解决,从而达到事半功倍的效果。