How to store a C++ variable in a register

25,028

Solution 1

You can't. It is only a hint to the compiler that suggests that the variable is heavily used. Here's the C99 wording:

A declaration of an identifier for an object with storage-class specifier register suggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-defined.

And here's the C++11 wording:

A register specifier is a hint to the implementation that the variable so declared will be heavily used. [ Note: The hint can be ignored and in most implementations it will be ignored if the address of the variable is taken. This use is deprecated (see D.2). —end note ]

In fact, the register storage class specifier is deprecated in C++11 (Annex D.2):

The use of the register keyword as a storage-class-specifier (7.1.1) is deprecated.

Note that you cannot take the address of a register variable in C because registers do not have an address. This restriction is removed in C++ and taking the address is pretty much guaranteed to ensure the variable won't end up in a register.

Many modern compilers simply ignore the register keyword in C++ (unless it is used in an invalid way, of course). They are simply much better at optimizing than they were when the register keyword was useful. I'd expect compilers for niche target platforms to treat it more seriously.

Solution 2

The register keyword has different meanings in C and C++. In C++ it is in fact redundant and seems even to be deprecated nowadays.

In C it is different. First don't take the name of the keyword literally, it is has not always to do with a "hardware register" on a modern CPU. The restriction that is imposed on register variables is that you can't take their address, the & operation is not allowed. This allows you to mark a variable for optimization and ensure that the compiler will shout at you if you try to take its address. In particular a register variable that is also const qualified can never alias, so it is a good candidate for optimization.

Using register as in C systematically forces you to think of every place where you take the address of a variable. This is probably nothing you would want to do in C++, which heavily relies on references to objects and things like that. This might be a reason why C++ didn't copy this property of register variables from C.

Solution 3

Generally it's impossibly. Specifically one can take certain measures to increase the probability:

Use proper optimization level eg. -O2

Keep the number of the variables small

register int a,b,c,d,e,f,g,h,i, ... z;  // can also produce an error
// results in _spilling_ a register to stack
// as the CPU runs out of physical registers

Do not take an address of the register variable.

register int a;
int *b = &a;  /* this would be an error in most compilers, but
                 especially in the embedded world the compilers
                 release the restrictions */

In some compilers, you can suggest

register int a asm ("eax");  // to put a variable to a specific register

Solution 4

Generally CPP compilers(g++) do quite a few optimizations to the code. So when you declare a register variable, it is not necessary that the compiler will store that value directly in the register. (i.e) the code 'register int x' may not result in compiler storing that int directly in the register. But if we can force the compiler to do so, we may be successful.

For example, if we use the following piece of code, then we may force the compiler to do what we desire. Compilation of the following piece of code may error out, which indicates that the int is actually getting stored directly in the register.

int main() {
    volatile register int x asm ("eax"); 
    int y = *(&x);
    return 0;
}

For me, g++ compiler is throwing the following error in this case.

[nsidde@nsidde-lnx cpp]$ g++ register_vars.cpp 
register_vars.cpp: In function ‘int main()’:
register_vars.cpp:3: error: address of explicit register variable ‘x’ requested

The line 'volatile register int x asm ("eax")' is instructing the compiler that, store the integer x in 'eax' register and in doing so do not do any optimizations. This will make sure that the value is stored in the register directly. That is why accessing the address of the variable is throwing an error.

Alternatively, the C compiler (gcc), may error out with the following code itself.

int main() {
    register int a=10;
    int c = *(&a);
    return 0;
}

For me, the gcc compiler is throwing the following error in this case.

[nsidde@nsidde-lnx cpp]$ gcc register.c 
register.c: In function ‘main’:
register.c:5: error: address of register variable ‘a’ requested

Solution 5

It's just a hint to the compiler; you can't force it to place the variable in a register. In any event, the compiler writer probably has much better knowledge of the target architecture than the application programmer, and is therefore better placed to write code that makes register allocation decisions. In other words, you are unlikely to achieve anything by using register.

Share:
25,028
ashutosh kumar
Author by

ashutosh kumar

Updated on May 19, 2020

Comments

  • ashutosh kumar
    ashutosh kumar about 4 years

    I would like some clarification regarding a point about the storage of register variables: Is there a way to ensure that if we have declared a register variable in our code, that it will ONLY be stored in a register?

    #include<iostream>
    
    using namespace std;
    
    int main()
    {
        register int i = 10;// how can we ensure this will store in register only.
        i++;
        cout << i << endl;
        return 0;
    }
    
  • Pete Becker
    Pete Becker about 11 years
    It always surprised me to see code that marked every local variable with register.
  • Joseph Mansfield
    Joseph Mansfield about 11 years
    @PeteBecker Who needs RAM? I'm all registers!
  • Jens Gustedt
    Jens Gustedt about 11 years
    your argumentation is C++ only. C imposes restrictions on register variables. Also your example from gcc about asm is misleading. For gcc this is not a "suggestion". If you specify a register, that register should exist and will be used.
  • Jens Gustedt
    Jens Gustedt about 11 years
    your argumentation is C++ only. C imposes restrictions on register variables.
  • Jens Gustedt
    Jens Gustedt about 11 years
    your argumentation is C++ only. C imposes restrictions on register variables.
  • Joseph Mansfield
    Joseph Mansfield about 11 years
    @JensGustedt It is still only a hint in C. I noted when I was specifically talking about C++. I fleshed the answer out a bit more.
  • Hot Licks
    Hot Licks about 11 years
    Ah, makes one yearn for the days when you could code register(4) and the var would end up in register 4. (Then you'd follow with several gen procedure calls to do your assembly stuff.)
  • jthill
    jthill about 11 years
    haha, 18 terminals on 2MB. get off my lawn :-) CP-67 was supporting 60 users on half that.
  • Jens Gustedt
    Jens Gustedt about 11 years
    @sftrabbit, no in is not only a hint in C. In C taking the address of a register variable is a constraint violation. That is a real semantical difference. Programs that compile for C++ wouldn't for C.
  • Mats Petersson
    Mats Petersson about 11 years
    Yeah, my school shared a 2MB PDP-11 running RSTS-E, and it had 8 terminals and one printer at my school, 8+1 at the next school, and then the main school had two rooms with 16 terminals in each room (plus a few random terminals scattered about in a few other places). And there was a C compiler for that, but most of us used the language that was modern at the time, Pascal.
  • Jeff Hammond
    Jeff Hammond about 11 years
    I think you meant "literally" (or "verbatim") instead of "verbose" in the first sentence of paragraph two.
  • benathon
    benathon over 6 years
    This asm("eax") syntax is exactly what I was looking for. thanks for actually answering the question
  • Peter Cordes
    Peter Cordes over 4 years
    GCC docs have been updated: register ... asm() local variables no longer guarantee anything except picking that register for an "r" constraint. In practice GCC does still use the specified registers; clang doesn't outside of asm statements. Related: Reading a register value into a C variable
  • David Wohlferd
    David Wohlferd about 4 years
    He didn't link to the docs for that usage of asm which contains useful information. In particular: The only supported use for this feature is to specify registers for input and output operands when calling Extended asm. So there's no guarantee that any specific value will be in eax at any particular time, unless/until you call extended asm. Which leads right back to what everyone else is saying: it doesn't really mean much anymore.
  • ABaumstumpf
    ABaumstumpf almost 4 years
    Not even close. Volatile forces the compiler to assume any access to the variable has visible side-effects and those are enforced to not change due to optimisations. That means it simply can not re-order statements with visible sideeffects.