How to store a C++ variable in a register

前提是你 提交于 2019-12-09 08:30:28

问题


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

回答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.




回答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.




回答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



回答4:


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.




回答5:


The "register" keyword is a remnant of the time when compilers had to fit on machines with 2MB of RAM (shared between 18 terminals with a user logged in on each). Or PC/Home computers with 128-256KB of RAM. At that point, the compiler couldn't really run through a large function to figure out which register to use for which variable, to use the registers most effectively. So if the programmer gave a "hint" with register, the compiler would put that in a register (if possible).

Modern compilers don't fit several times in 2MB of RAM, but they are much more clever at assigning variables to registers. In the example given, I find it very unlikley that the compiler wouldn't put it in a register. Obviously, registers are limited in number, and given a sufficiently complex piece of code, some variables will not fit in registers. But for such a simple example, a modern compiler will make i a register, and it will probably not touch memory until somewhere inside ostream& ostream::operator<<(ostream& os, int x).




回答6:


The only way to ensure that you are using a register, is to use inline assembly. But, even if you do this, you are not guaranteed that the compiler won't store your value outside of the inline assembly block. And, of course, your OS may decide to interrupt your program at any point, storing all your registers to memory, in order to give the CPU to another process.

So, unless you write assembler code within the kernel with all interrupts disabled, there is absolutely no way to ensure that your variable will never hit memory.

Of course, that is only relevant if you are concerned about safety. From a performance perspective, compiling with -O3 is usually enough, the compiler usually does quite a good job at determining which variables to hold in registers. Anyway, storing variables in registers is only one small aspect of performance tuning, the much more important aspect is to ensure that no superfluous or expensive work gets done in the inner loop.




回答7:


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



回答8:


Here you can use volatile register int i = 10 in C++ to ensure i to be stored in register. volatile keyword will not allow the compiler to optimize the variable i.



来源:https://stackoverflow.com/questions/15908835/how-to-store-a-c-variable-in-a-register

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!