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

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

按我的理解,答案是YESNO.

不,因为,

  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;
}
Run Code Online (Sandbox Code Playgroud)

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

请纠正我或提供更多输入.:-)

  • 你的for循环可以由编译器展开并且只使用寄存器,编译器一直都在做这种事情(甚至计算循环中的所有数学,并删除大块代码.但是当然是相反的参数你的函数是数组的索引,不能在编译时计算,然后你仍然可以使用if-then-else树或跳转表这样的开关,但是为了使用内存可能更聪明,但是是特定于代码的. (3认同)
  • 数组元素只需要在C模型中可寻址.由于C标准中的"as if"规则,它不需要在编译器生成的实际代码中可寻址.类似地,数组元素只需要在C模型中的连续内存位置,而不是在实际内存中. (2认同)

Jen*_*edt 8

不要将register关键字与CPU寄存器混合使用.你的代码

register int arr[4];
Run Code Online (Sandbox Code Playgroud)

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


Eri*_*hil 6

我写了这段代码:

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寄存器中保留一小组值并独立访问它们,前提是源代码引用可以在编译时解析为常量.


Jub*_*ian 5

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

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

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