views:

1116

answers:

6

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.

Thanks,

Naveen

A: 

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.

David Thornley
A: 

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

Konrad Rudolph
+2  A: 

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.

Blindy
Is answer is addressing the C or the C++ version of `register`? In the context of the question it's probably a good idea to note the differences.
Charles Bailey
Looks like its C++ from the quote above. It isn't that relevant though since this particular practice nets you absolutely nothing, you either make the compiler ignore your hint or outright error out on you, both results being not what you want and practically begging you not to do it!
Blindy
+18  A: 

Here's an excerpt from Section 6.7.1 (footnote 101) of the C99 standard (pdf):

The implementation may treat any register declaration simply as an auto declaration. However, whether or not addressable storage is actually used, the address of any part of an object declared with storage-class specifier register cannot be computed, either explicitly (by use of the unary & operator as discussed in 6.5.3.2) or implicitly (by converting an array name to a pointer as discussed in 6.3.2.1). Thus, the only operator that can be applied to an array declared with storage-class specifier register is sizeof.

And from Section 7.1.1, Paragraph 3 of the C++ standard (pdf):

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]

So, this seems like another case of C and C++ having "identical" features that behave the way you'd expect them most of the time, but diverge and cause confusion other times. In this situation, I think the way C does it makes sense since it

  • is semantically closest to being correct and;
  • doesn't do things behind your back.

Fun tidbits about register

The C++ group (WG21) wants to deprecate register:

The register keyword serves very little function, offering no more than a hint that a note says is typically ignored. It should be deprecated in this version of the standard, freeing the reserved name up for use in a future standard, much like auto has been re-used this time around for being similarly useless.

Notes from the March, 2009 meeting:

The consensus of the CWG was in favor of deprecating register.

Look what the C99 group (WG14) said about register (pdf) at a meeting:

General agreement to deprecate the “auto” keyword. Should we ask WG21 to go back to the previous use of “register” (no address)? No, this will not fly with WG21.

Andrew Keeton
Yay. Another thing to add to my list of arbitrary differences between C and C++. I would love to have heard the rationale for changing this.
Mark Bessey
In the old days it made sense for the programmer to specify variabels as register variables because the compilers were not that good. Nowadays the compiler is almost always going to do a better job of optimizations than a programmer, thus changing it to a hint is inline with the advancement of compiler technology.
Martin York
If you think you can optimize better than the compiler you are mistaken. If you actually find an optimization for some obscure hardware great, we will add it to the next version of the compiler and we are back to sqaure one the compiler is better than you.
Martin York
I wasn't arguing that "register" was useful, just that having arbitrary differences between C and C++ is a bad idea. The C++ version of "register" is arbitrarily different, but no more useful. It just adds to the code out there that compiles with a C++ compiler, but not with a C compiler. I had (naively) expected the C and C++ standards to tend to converge over time, or at least not diverge.
Mark Bessey
+1  A: 
Matthew Crumley
+3  A: 

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]

Tyler McHenry