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

Why register array names can be assigned to pointer variables without compiler error?

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

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

你能解释一下为什么数组名可以赋值给指针吗?或者,如果有人已经解释过了,请告诉我链接,以便我看一下以获得答案。谢谢。

这是我试过的:

我读了 cppreference,其中解释了 register 关键字,上面写着:

register arrays are not convertible to pointers.

此外,我阅读了 C89 草案,其中写道:

The implementation may treat any register declaration simply as an auto declaration. However, whether or not addressable storage is actually used, the address of any part of an object declared with storage-class specifier register may not be computed, either explicitly (by use of the unary & operator as discussed in 3.3.3.2) or implicitly (by converting an array name to a pointer as discussed in 3.2.2.1). Thus the only operator that can be applied to an array declared with storage-class specifier register is sizeof.

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

此外,为了找到答案,我在这里搜索并找到了这个问题: Address of register variable。有很好的答案,但是还是找不到我想要的答案。

这是我测试过的代码。我通过 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]; 出现编译错误。

这是 Clang 编译器中的错误。 GCC shows an error on both lines.

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

… If the array object has register storage class, the behavior is undefined.

此外,C 2018 脚注 124 说:

… the address of any part of an object declared with storage-class specifier register cannot be computed, either explicitly (by use of the unary & operator as discussed in 6.5.3.2) or implicitly (by converting an array name to a pointer as discussed in 6.3.2.1)…

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

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