首页 > 解决方案 > 为什么可以将寄存器数组名称分配给指针变量而不会出现编译器错误?

问题描述

register我对C 中的关键字有疑问。

我发现register数组名称(例如array)可以分配给指针变量,而&array[0]不能。

你能解释一下为什么数组名可以分配给指针吗?或者,如果有人已经解释过,请让我知道链接,以便我查看答案。谢谢你。

这是我尝试过的:

我读了解释关键字的cppreference ,它说:register

寄存器数组不能转换为指针。

另外,我阅读了 C89 草案,其中说:

实现可以将任何寄存器声明简单地视为自动声明。但是,无论是否实际使用可寻址存储,使用存储类说明符寄存器声明的对象的任何部分的地址都可能不会被计算,无论是显式(通过使用 3.3.3.2 中讨论的一元 & 运算符)还是隐式(通过将数组名称转换为指针,如 3.2.2.1 中所述)。因此,唯一可以应用于使用存储类说明符寄存器声明的数组的运算符是 sizeof。

看起来我无法将寄存器数组名称分配给指针以获取其地址。

此外,为了找到答案,我在这里搜索并找到了这个问题: 寄存器变量地址。有很好的答案,但是,我仍然找不到我想要的答案。

这是我测试的代码。我通过带有标志的Clang编译了这段代码-std=c89

register int array[10];
int* p;

p = array;     // Compiled without warning or error
p = &array[0]; // Compiled with error which I expected

我预计两者p = array;p = &array[0];导致编译错误,但仅p = &array[0];产生编译错误。

标签: cclangc89storage-class-specifierregister-keyword

解决方案


这是 Clang 编译器中的一个错误。 GCC 在两行都显示错误。

在讨论“类型数组”到“类型指针”的自动转换时,C 2018 6.3.2.1 说:

… 如果数组对象有寄存器存储类,则行为未定义。

此外,C 2018 脚注 124 说:

register...无法计算使用存储类说明符声明的对象的任何部分的地址,无论是显式(通过使用&6.5.3.2 中讨论的一元运算符)还是隐式(通过将数组名称转换为指针,如 6.3 中讨论的) .2.1)…</p>

显然,p = array;转换array为指针,如 6.3.2.1 中所讨论的,但是这个脚注(它是非规范性的,但在这种情况下非常明确地告诉我们意图)说该指针的值无法计算。

由于行为不是由 C 标准定义的,因此 C 实现可以将其定义为扩展。array但是, and之间的不一致行为&array[0]表明这不是 Clang 故意扩展的,而是一个错误。


推荐阅读