Address of register variable

2019-01-06 19:45发布

In C, we cannot use & to find out the address of a register variable but in C++ we can do the same. Why is it legal in C++ but not in C? Can someone please explain this concept in-depth.

8条回答
甜甜的少女心
2楼-- · 2019-01-06 20:16

A register variable doesn't have an address, it's held (at least it's supposed to be held) in a cpu register. Since the register modifier is nothing but a hint, if you force the compiler to generate code to extract it's address, the modifier will be ignored and you'll end up with a regular variable held in memory.

To directly answer your question, whichever one lets you take a register variable's address (your original post is contradicting itself..) lets you ignore your own hint and should at least issue a warning. IMO the correct implementation would be to disallow taking the address of a register variable.

查看更多
Viruses.
3楼-- · 2019-01-06 20:16

C and C++ are two different languages, with a large common subset. That's why some things are different between them.

While I don't understand your question, register is (at least in C++) a hint that a variable might be accessed more frequently, and nothing more. In C, it means you can't take the address with the & unary operator, which made a certain amount of sense at the time. In the early days of C, it was expected that the compiler might not bother allocating memory for the variable, and so there would not necessarily be an address to take.

(Computers normally have registers, which are quick-access parts of the CPU, and hence the fastest storage to access. A variable might live in a register, rather than in memory, if that caused better performance.)

Nowadays, almost all compilers are sophisticated enough to do their own allocation better than the programmer can, so using register is almost always pointless.

查看更多
一纸荒年 Trace。
4楼-- · 2019-01-06 20:21

Sorry about the super late answer.

The problem is that, in C, register originally meant storing values in a register which is why only int and char can be used for it. But with time and especially standard C++, it broadened to "fast access" rather than "in register of CPU". So in C++, an array maybe a register type but we know that it is not possible to store arrays in a CPU register. Hence, it is logically okay to address a C++ register (in the above sense), but will still make no sense if the values are actually in a CPU register.

查看更多
We Are One
5楼-- · 2019-01-06 20:23

The register keyword is a hint only and can be ignored. Most C++ compilers ignore it all of the time, but any C++ compiler will ignore it if you take the address of the variable, or create a reference to it.

On the other hand, a C++ compiler doesn't have to ignore "register" just because you take the variable's address. In theory the compiler could store it in a register and give you some magic pointer value that is somehow mapped to the register behind the scenes, but that would be a lot of work for very little gain, so no compiler (that I know of) does anything like that.

Since register is ignorable in C as well, I suspect that the explicit proscription against taking addresses of register variables was simply to alleviate C compilers from the burden of checking for this.

The relevant part of the C++ standard is 7.1.1.3:

A register specifier has the same semantics as an auto specifier together with a hint to the implementation that the object 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 object is taken. —end note]

查看更多
放我归山
6楼-- · 2019-01-06 20:26

I assume that the keyword wouldn't have even made it into the language if it weren't for C compatibility. While I can not speak with any authority, if this is so, it seems to me there is a practical reason for it to be legal beyond simply a standard-enforced "the compiler is smarter than you" clause: C++ takes addresses of things without permission more readily than C does. Specifically: member functions, and references.

Because member functions require an implicit this parameter, it would be impossible to call them from an object declared register. In C, there is nothing prohibiting you from saying register struct X x;, so such language would have to be allowed in C++ [since C-compatibility is the whole reason the keyword even exists]. But if you prohibit calling member functions as well as taking addresses, that also covers the initial constructor call. In essence, it would not work on non-POD types. So you end up with one storage class specifier that is only valid for a small subset of the legal types, when all the rest can be used for anything.

You also could not create references to such objects, even though, technically, the compiler does not have to treat references as pointers. register int i; int& x; is not required to have space for two variables, but if you later do &x you end up with a pointer to i. So the initial construct has to be rendered illegal. While this seems like a non-issue, since references don't exist in C anyhow, returning to our previous point, POD types declared with the register specifier can no longer be copied. The compiler-provided copy constructor is of the form X::X(const X&) or X::X(X&) as appropriate.

So, in order to maintain C compatibility, they have to make register unique as a storage class specifier in that it does not apply to all types, and modify at least two different parts of the standard elsewhere [to specify that you can not create a reference to a variable declared with the register specifier, and to somehow work around the references for POD copying]. Or, they could just say "its okay to take the address" and let compilers decide whether or not to honor the requests. Something they were planning on doing anyhow.

查看更多
一纸荒年 Trace。
7楼-- · 2019-01-06 20:28

This is an educated guess only, but I doubt that you can take the address of a register in C++ because such a think simply doesn't exist. C++ probably doesn't use a register in your particular case. Notice that the storage class qualifier register is only a hint to the compiler (and most if not all modern compilers happily ignore it completely).

查看更多
登录 后发表回答