是否可以将整个数组保存在cpu寄存器中

在下面的代码中,

int main( ) { register int arr[4]; /* ... */ } 

是否有可能在某些cpu寄存器中分配’arr’。 (考虑cpu有4个或更多寄存器)。

或者编译器会忽略数组的寄存器存储类。

根据我的理解,答案是肯定的 ,不是。

不,因为,

  1. 任何数组元素必须是显式可寻址的(例如,对于16位uC / uP,其地址应始终位于0x0000至0xFFFF地址空间之间。)

  2. 使用寄存器直接寻址模式(例如mov r2,#100 )访问CPU寄存器。 该寻址模式没有有效地址。 ( 即使它不被认为是寻址模式

  3. 数组元素必须位于连续的内存位置。 (用于指针运算,使用数组的主要原因)

是的因为,

  1. 编译器可以为上面的数组分配寄存器,这样我们就可以对它执行一些有限的操作。 但是不能使用内部使用地址进行优化的操作。

见下面的代码。

 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; } 

所以我的最后结论是,理想情况下,即使编译器允许, 寄存器存储类也不应该与数组一起使用。

请纠正我或提供更多输入。 🙂

不要将register与CPU寄存器混合为关键字。 你的代码

 register int arr[4]; 

使得arr完全无法访问,因为您无法获取对象的地址。 基本上你唯一可以做的就是sizeof arr

我写了这段代码:

 int foo(int x, int y) { register int a[2] = {x, y}; return a[0] + a[1]; } 

并使用带有Apple clang 4.0版的cc -O3 -std=c99 -S编译它,并生成此程序集(省略了各种调试和不相关的装饰):

 _foo: pushq %rbp movq %rsp, %rbp addl %esi, %edi movl %edi, %eax popq %rbp ret 

因此,从某种意义上说,数组保存在寄存器中。 然而,这更像是优化的工件,并且所有对数组的引用都是通过常量索引而不是由于register关键字。 所以答案是“嗯,从理论上讲,它可能会发生。 但它很少或没有实际用途,你通常不能依赖它。“

某些处理器具有可索引的寄存器,例如ARM处理器上的NEON寄存器,其中包含多个值,这些值可以在某些指令中独立寻址(通过立即值)。 我可以设想编译器在NEON寄存器中保留一小组值并独立访问它们,前提是源代码引用可以在编译时解析为常量。

C89标准不允许对寄存器存储类的变量进行地址或任何类似的操作(至少我没有的草案:3.5.1,参见注释49)。 它甚至提到只有sizeof运算符对这样的数组有效。 C99标准是指6.7.1中的寄存器存储类,其中注释103声明与C89草案完全相同。

因此总之,寄存器存储类和数组应该不会混合。 声明本身是有效的,但从技术上讲它是无用的。

否则一般情况下,如果您有疑问,请检查反汇编列表。 一些针对8位控制器的编译器可能会做一些令人惊讶的事情。

优化编译器可能会临时分配它认为适合CPU寄存器的任何这些数组元素,并且只会在那里进行操作。

但是如果你问是否有可能强制该数组进行寄存器,那么我不知道如何做到这一点。 对于单变量(在gcc中),您可以使用“显式寄存器变量”(请参阅http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html )。