Rah*_*wre 9 c compiler-construction embedded microcontroller microprocessors
在下面的代码中,
int main( )
{
register int arr[4];
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
是否有可能在某些cpu寄存器中分配'arr'.(考虑cpu有4个或更多寄存器).
或者编译器会忽略数组的寄存器存储类.
Rah*_*wre 11
按我的理解,答案是YES和NO.
不,因为,
任何数组元素必须是显式可寻址的(例如,对于16位uC/uP,其地址应始终位于0x0000至0xFFFF地址空间之间.)
使用寄存器直接寻址模式(例如mov r2,#100)访问CPU寄存器.该寻址模式没有有效地址.(即使它不被认为是寻址模式)
数组元素必须位于连续的内存位置.(用于指针运算,使用数组的主要原因)
并且是因为,
见下面的代码.
int main( )
{
register int arr[4];
int i;
arr[0] = 10; /* OK */
arr[1] = 20; /* OK */
arr[2] = 30; /* OK */
arr[3] = 40; /* OK */
for(i=0;i<4;i++)
arr[i]=10; /* Error : "address of register variable 'arr' requested" */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以我的最后结论是,理想情况下,即使编译器允许,寄存器存储类也不应该与数组一起使用.
请纠正我或提供更多输入.:-)
不要将register关键字与CPU寄存器混合使用.你的代码
register int arr[4];
Run Code Online (Sandbox Code Playgroud)
使得arr完全无法访问,因为您无法获取对象的地址.基本上你唯一可以做的就是sizeof arr.
我写了这段代码:
int foo(int x, int y)
{
register int a[2] = {x, y};
return a[0] + a[1];
}
Run Code Online (Sandbox Code Playgroud)
并cc -O3 -std=c99 -S使用Apple clang 4.0版编译它,并生成此程序集(省略各种调试和无关的装饰):
_foo:
pushq %rbp
movq %rsp, %rbp
addl %esi, %edi
movl %edi, %eax
popq %rbp
ret
Run Code Online (Sandbox Code Playgroud)
因此,从某种意义上说,数组保存在寄存器中.然而,这更像是优化的工件,并且所有对数组的引用都是通过常量索引而不是由register关键字引起的.所以答案是"嗯,从理论上讲,它可能会发生.但它很少或没有实际用途,你通常不能依赖它."
某些处理器具有可索引的寄存器,例如ARM处理器上的NEON寄存器,其中包含可在某些指令中独立寻址(通过立即值)的多个值.我可以设想编译器在NEON寄存器中保留一小组值并独立访问它们,前提是源代码引用可以在编译时解析为常量.
C89标准不允许对寄存器存储类的变量进行地址或任何类似的操作(至少我没有的草案:3.5.1,参见注释49).它甚至提到只有sizeof运算符对这样的数组有效.C99标准是指6.7.1中的寄存器存储类,其中注释103声明与C89草案完全相同.
因此总之,寄存器存储类和数组应该不会混合.声明本身是有效的,但从技术上讲它是无用的.
否则一般情况下,如果您有疑问,请检查反汇编列表.一些针对8位控制器的编译器可能会做一些令人惊讶的事情.