c - 为什么可以将寄存器数组名称分配给指针变量而不会出现编译器错误?
问题描述
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];
产生编译错误。
解决方案
这是 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 故意扩展的,而是一个错误。
推荐阅读
- python - 在烧瓶中获取 HTML 输入并返回数据
- c# - 在数组初始化中指定特定值
- android - Android:Toast 在函数执行后显示,期望它在之前显示
- vb.net - VB.Net: Access Base class variable from derived class
- c++ - 动画问题 - 翻译、投影 OpenGL/C++
- reactjs - 类型错误:this.checkPositions 不是 React 函数
- c - 重定向子进程而不重定向父进程
- c# - 从客户端连接到 SignalR 服务器
- c# - c#(.NET Framework)上的Visual Studio Community 2019 加载缓慢(无需调试即可启动)
- salesforce - 我想同时学习 Salesforce 管理员和开发人员?