如何在寄存器中存储 C++ 变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15908835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:53:08  来源:igfitidea点击:

How to store a C++ variable in a register

c++inline-assemblycpu-registers

提问by ashutosh kumar

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

回答by Joseph Mansfield

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

你不能。这只是对编译器的一个提示,表明该变量被大量使用。这是C99的措辞:

A declaration of an identi?er for an object with storage-class speci?er registersuggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-de?ned.

具有存储类register说明的对象的标识符声明表明对对象的访问尽可能快。这些建议的有效程度是由实施决定的。

And here's the C++11 wording:

这是 C++11 的措辞:

A registerspecifier 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 ]

一个register说明符是一种提示,如此声明的变量将被频繁使用的实现。[ 注意:可以忽略提示,并且在大多数实现中,如果采用变量的地址,它将被忽略。这种用法已被弃用(见 D.2)。——尾注]

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

事实上,register存储类说明符在 C++11(附录 D.2)中已被弃用:

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

不推荐使用register关键字作为存储类说明符(7.1.1)。

Note that you cannot take the address of a registervariable 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.

请注意,您不能register在 C 中获取变量的地址,因为寄存器没有地址。此限制在 C++ 中被删除,并且几乎可以保证获取地址以确保变量不会在寄存器中结束。

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

许多现代编译器简单地忽略registerC++ 中的关键字(当然,除非它以无效方式使用)。与register关键字有用时相比,它们在优化方面要好得多。我希望小众目标平台的编译器更认真地对待它。

回答by Jens Gustedt

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

register关键字在 C 和 C++ 中具有不同的含义。在 C++ 中,它实际上是多余的,现在甚至似乎已被弃用。

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 registervariables 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 registervariable that is also constqualified can never alias, so it is a good candidate for optimization.

在 C 中则不同。首先不要从字面上理解关键字的名称,它并不总是与现代 CPU 上的“硬件寄存器”有关。对register变量施加的限制是不能取它们的地址,&不允许操作。这允许您标记一个变量以进行优化,并确保编译器在您尝试获取其地址时会对您大喊大叫。特别是一个register也被const限定的变量永远不能别名,所以它是一个很好的优化候选者。

Using registeras 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 registervariables from C.

register在 C 中使用as 系统地迫使您考虑获取变量地址的每个位置。这可能不是您在 C++ 中想要做的,它严重依赖于对对象的引用和类似的东西。这可能是 C++ 没有register从 C复制变量的这个属性的原因。

回答by Aki Suihkonen

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

一般是不可能的。具体可以采取一定的措施来增加概率:

Use proper optimization level eg. -O2

使用适当的优化级别,例如。 -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

回答by NPE

It's just a hint to the compiler; you can't forceit 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.

这只是给编译器的一个提示;你不能强迫它把变量放在寄存器中。无论如何,编译器编写者可能比应用程序程序员更了解目标体系结构,因此更适合编写做出寄存器分配决策的代码。换句话说,您不太可能通过使用register.

回答by Mats Petersson

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).

“注册”关键字是编译器必须适合具有 2MB RAM 的机器(在 18 个终端之间共享,每个终端共享一个用户)时的残余。或具有 128-256KB RAM 的 PC/家用计算机。那时,编译器无法真正运行一个大函数来确定哪个寄存器用于哪个变量,以最有效地使用寄存器。因此,如果程序员用 给出“提示” register,编译器会将其放入寄存器(如果可能)。

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 ia register, and it will probably not touch memory until somewhere inside ostream& ostream::operator<<(ostream& os, int x).

现代编译器在 2MB 的 RAM 中多次容纳不下,但它们在将变量分配给寄存器方面要聪明得多。在给出的例子中,我发现编译器不会把它放在寄存器中是非常不可能的。显然,寄存器的数量是有限的,并且给定一段足够复杂的代码,一些变量将无法放入寄存器中。但是对于这样一个简单的例子,现代编译器会创建i一个寄存器,并且它可能直到在ostream& ostream::operator<<(ostream& os, int x).

回答by cmaster - reinstate monica

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 outsideof 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.

确保您使用寄存器的唯一方法是使用内联汇编。但是,即使您这样做,也不能保证编译器不会在内联汇编块之外存储您的值。而且,当然,您的操作系统可能会决定随时中断您的程序,将您的所有寄存器存储到内存中,以便将 CPU 交给另一个进程。

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 -O3is 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.

当然,这仅在您担心安全时才有意义。从性能的角度来看,编译-O3通常就足够了,编译器通常在确定哪些变量要保存在寄存器中方面做得很好。无论如何,将变量存储在寄存器中只是性能调整的一个小方面,更重要的方面是确保在内循环中不会完成多余或昂贵的工作。

回答by Nagakishore Sidde

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.

通常 CPP 编译器(g++)对代码做了很多优化。因此,当您声明一个寄存器变量时,编译器不必将该值直接存储在寄存器中。(即)代码“register int x”可能不会导致编译器将该 int 直接存储在寄存器中。但是如果我们可以强制编译器这样做,我们可能会成功。

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 实际上是直接存储在寄存器中的。

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.

对我来说,在这种情况下,g++ 编译器会抛出以下错误。

[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.

'volatile register int x asm ("eax")' 行指示编译器将整数 x 存储在 'eax' 寄存器中,并且这样做不进行任何优化。这将确保该值直接存储在寄存器中。这就是为什么访问变量的地址会引发错误的原因。

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

或者,C 编译器 (gcc) 可能会因以下代码本身而出错。

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

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

对我来说,gcc 编译器在这种情况下会抛出以下错误。

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

回答by sree

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

这里可以volatile register int i = 10在C++中使用,以确保i存储在寄存器中。volatile关键字将不允许编译器优化变量i