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 anauto
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 specifierregister
issizeof
.
And from Section 7.1.1, Paragraph 3 of the C++ standard (pdf):
A
register
specifier has the same semantics as anauto
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 likeauto
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.
//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>
using namespace std;
int main()
{
int i = 123;
auto int j = 456;
register int k = 789;
cout<<"Address of i = " << &i <<", Value = " << i << endl;
cout<<"Address of j = " << &j <<", Value = " << j << endl;
cout<<"Address of k = " << &k <<", Value = " << k << endl;
return 0;
}
When programming at the firmware level, the keyword "register" is used to indicate the existence of a memory location defined in the hardware as a having a special function. For example, the PC (program counter) is a "register". There may be a special purpose hardware "register" that may need writing to or reading from to get a task done. The keyword "register" along with the address of the memory location is needed in order to indicate to the compiler that it must access that particular memory location for these actions. So the interpretation of the keyword "register" depends on the compilers target system.
ReplyDeleteI was searching on google and directed to this blog. I found it very informative. There are some very useful examples. Great work, Keep it up!
ReplyDeleteWhat the author might have missed here is that the compiler might have been forced to create an auto storage for the k variable, as an address for the variable was requested. A better test would be to disassemble to code:
ReplyDelete#include
int main(int argc, char **argv) {
int i = 1;
auto int j = 2;
register int k = 3;
register int l = 4;
std::cout << i << " " << j << " " << k << " " << &l << std::endl;
return 0;
}
Snippet of assembly shows:
movl $1, -16(%rbp)
movl $2, -12(%rbp)
movl $3, %ebx
movl $4, -20(%rbp)
At least my compiler is still respecting the register (though not recommending the coding style).