6

众所周知,使用寄存器存储类声明的变量的地址不能被取走。所以我尝试使用 register 关键字创建一个数组并尝试访问该元素。但我注意到编译器没有引发任何错误。

#include <stdio.h>
void main()
{
   register int x[]={3,4};
   printf("%d\n",x[0]); // compiled successfully
  // printf("%d",&x[0]);// compiler raises an error
}

众所周知,编译器会将表达式 x[0] 转换为 *(x+0),其中 x 表示基地址。但是,既然数组是用寄存器存储类声明的,怎么可能得到数组的基地址呢?

提前致谢..

4

1 回答 1

6

在C标准下,可以声明一个带有register存储类的数组,但基本没用;任何使用该数组形成指针的尝试,更不用说取消引用该指针(访问数组的元素),都会导致未定义的行为。C17 (n2176) 6.3.2.1 (3):

除非它是 sizeof 运算符的操作数,或一元 & 运算符,或者是用于初始化数组的字符串字面量,否则类型为“类型数组”的表达式将转换为类型为“类型指针”的表达式指向数组对象的初始元素并且不是左值。 如果数组对象具有寄存器存储类,则行为未定义。

事实上,正如脚注 123 到 6.7.1 (6) 中所强调的那样,您可以合法地对数组做的几乎唯一的事情就是拿走它。registersizeof

所以你的例子有未定义的行为;完全由编译器决定如何处理它。一个合理的选择,以及您可能会做的,就是忽略register关键字并将数组视为任何其他数组。这是明智的,因为现代编译器在几乎所有其他情况下都会忽略register关键字,并自行决定何时将变量优化到寄存器中。不允许忽略的一件事是尝试应用&运算符,因为这违反了 6.5.3.2 (1) 的约束,这解释了为什么在尝试这样做时会出现错误。

于 2021-04-12T02:50:39.490 回答