Frage

In below code,

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

Is it possible that 'arr' is allocated in some cpu register. (Consider cpu has 4 or more registers).

Or compiler will ignore register storage class for array.

War es hilfreich?

Lösung

As per my understanding, answer is YES and NO.

NO because,

  1. Any array element must be explicitly addressable (i.e. for eg. for 16 bit uC/uP its address should always lie between 0x0000 to 0xFFFF address space.)

  2. CPU registers are accessed using register direct addressing mode ( such as mov r2,#100 ). This addressing mode does not have an effective address. ( even it is not considered to be an addressing mode )

  3. Array elements must reside in continous memory locations. ( for pointer arithmetic, the main reason to use array )

and YES because,

  1. Compiler can allocate register for above array, so that we can perform some limited operations on it. But operations which internally uses address for optimizations can't be used.

See below code.

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

So my final conclusion is that, ideally register storage class should never be used with array even if your compiler permits it.

Please correct me or give more inputs. :-)

Andere Tipps

Don't mix register as a keyword with CPU registers. Your code

register int arr[4];

makes that arr is completely inaccessible, since you can't take the address of the object. Basically the only thing that you can do with it is sizeof arr.

I wrote this code:

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

and compiled it with cc -O3 -std=c99 -S with Apple clang version 4.0, and it produces this assembly (various debugging and irrelevant decorations omitted):

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

So, in a sense, the array was kept in registers. However, this was more an artifact of optimization and the fact that all references to the array are via constant indices rather than due to the register keyword. So the answer is “Well, in theory, it can happen. But it is of little or no practical use, and you generally cannot rely on it.”

Some processors have indexable registers, such as NEON registers on ARM processors, which contain multiple values that can be independently addressed (via immediate values) in certain instructions. I could envision a compiler keeping a small array of values in a NEON register and accessing them independently, provided the source code references could be resolved to constants at compile time.

The C89 standard does not permit taking the address of or any similar operation on a variable of register storage class (at least the draft I have does not: 3.5.1, referring to note 49). It even mentions that only the sizeof operator is valid for such an array. The C99 standard refers to the register storage class in 6.7.1, where note 103 declares exactly the same as the C89 draft.

So in conclusion the register storage class and array should really not be mixed. The declaration itself is valid, but technically it is useless.

Otherwise in general when you are in doubt, check the disassembly listing. Some compilers targeting 8 bit controllers may do some surprising things.

Optimizing compiler will probably temporarily allocate any of these array elements it sees fit to CPU registers and will just do operations there.

But if you are asking if it is possible to force that array to registers, then I don't know how this could be done. For single variable (in gcc) you can use "explicit register variables" (see http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top