How to store a C++ variable in a register
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
.
ashutosh kumar
Updated on May 19, 2020Comments
-
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 about 11 yearsIt always surprised me to see code that marked every local variable with
register
. -
Joseph Mansfield about 11 years@PeteBecker Who needs RAM? I'm all registers!
-
Jens Gustedt about 11 yearsyour argumentation is C++ only. C imposes restrictions on
register
variables. Also your example from gcc aboutasm
is misleading. For gcc this is not a "suggestion". If you specify a register, that register should exist and will be used. -
Jens Gustedt about 11 yearsyour argumentation is C++ only. C imposes restrictions on register variables.
-
Jens Gustedt about 11 yearsyour argumentation is C++ only. C imposes restrictions on register variables.
-
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 about 11 yearsAh, 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 severalgen
procedure calls to do your assembly stuff.) -
jthill about 11 yearshaha, 18 terminals on 2MB. get off my lawn :-) CP-67 was supporting 60 users on half that.
-
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 about 11 yearsYeah, 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 about 11 yearsI think you meant "literally" (or "verbatim") instead of "verbose" in the first sentence of paragraph two.
-
benathon over 6 yearsThis
asm("eax")
syntax is exactly what I was looking for. thanks for actually answering the question -
Peter Cordes over 4 yearsGCC 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 ofasm
statements. Related: Reading a register value into a C variable -
David Wohlferd about 4 yearsHe 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 almost 4 yearsNot 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.