Why was the register keyword created?

While reading Keywords that are not (or, comments from another name) , Herb Sutter I came across these lines:

Correctly, some keywords are semantically equivalent to a space, the glorified comment.

and

We saw why the C ++ language treats keywords as reserved words, and we saw two keywords β€”auto and register β€” which make no sense difference for the C ++ program. Do not use them; they are just spaces anyway, and there are faster ways to enter spaces.

If keywords like auto (maybe not in C ++ 11) and register don't matter, then why were they created and used?

If you do not need to include register before the variable

 #include<stdio.h> int main(){ register int a = 15; printf("%d\n%d\n",&a,a); return 0; } 

Why is the above program reporting an error?

test_register.c: In the main function:

test_register.c: 4: 2: error: register variable address' requested

E ("% d \ n% r \ n", & a, a);

The following program works in C ++.

 #include<iostream> int main(){ register int a = 15; std::cout<<&a<<'\n'<<a; return 0; } 
+42
c ++ c language-lawyer c ++ 11
May 26 '16 at 9:14
source share
3 answers

Register

In C, the register storage class was used as a hint to the compiler to express that the variable should preferably be stored in the register . Note that the hint for storing the register variable in the real register may or may not be executed, but in any case, the corresponding restrictions still apply. See C11, 6.7.1p6 (primary focus):

Declaring an identifier for an object with a register storage class specifier implies that access to the object should be as fast as possible. The extent to which such proposals are effective is determined by implementation. [footnote 121]

[footnote 121] An implementation can handle any register declaration just like an auto declaration. However, regardless of whether address storage is actually used, the address of any part of an object declared using the register storage class specifier cannot be calculated either explicitly (using the unary and as operator, discussed in 6.5.3.2) or implicitly ( by converting the array name to a pointer, as described in 6.3.2.1). Thus, the only operators that can be applied to an array declared using the register storage class specifier are sizeof and _Alignof .

In C ++, this is just an unused reserved keyword, but it is reasonable to assume that it was stored for syntactic compatibility with C code.

auto

In C, the auto storage class defines an auto storage variable, but it is usually not used, since auto -functional variables are auto by default .

Similarly, it is reasonable to assume that it was originally ported to C ++ only for syntactic compatibility, although later it got its own meaning ( type of output ).

+51
May 26 '16 at 9:19
source share

register in C served for two purposes:

  • Tell the compiler that the variable should be stored in a register for performance. This usage is currently out of date.
  • Prevent the programmer from using the variable in such a way as to prevent it from being stored in the register. This use is only an outdated IMO.

It looks like const , which

  • Tips the compiler that a variable can be stored in read-only memory.
  • Prevents programming from writing a variable

As an example, consider this simplified function:

 int sum(const int *values, size_t length) { register int acc = 0; for (size_t i = 0; i < length; ++i) { acc += values[i]; } return acc; } 

The programmer wrote register to save the drive from the stack, avoiding writing memory every time it is updated. If the implementation is changed to something like this:

 // Defined in some other translation unit void add(int *dest, int src); int sum(const int *values, size_t length) { register int acc = 0; for (size_t i = 0; i < length; ++i) { add(&acc, values[i]); } return acc; } 

The variable acc can no longer be stored in the register when its address is taken to call add() , because the registers have no address. Thus, the compiler will flag &acc as an error, informing you that you probably destroyed the performance of your code by not allowing acc from living in a register.

This was much more important in the early days when compilers were dumber and variables could live in one place for an entire function. Currently, a variable can spend most of its life in the register, moving to the stack only temporarily when its address is busy. That is, this code:

 /* Passed by reference for some reason. */ void debug(const int *value); int sum(const int *values, size_t length) { int acc = 0; for (size_t i = 0; i < length; ++i) { acc += values[i]; } debug(&acc); return acc; } 

would make acc live on the stack for the whole function in older compilers. Modern compilers keep acc in the register until the debug() call.

Modern C code usually does not use the register keyword.

+25
May 26 '16 at 16:31
source share

C99 Justification provides another context for the register keyword:

Justification for the International Standard - Programming Languages ​​- C

Β§6.7.1 Storage class qualifiers

Since the address of the register variable is not possible, the objects of the register storage class effectively exist in a space different from other objects. (Functions take up a third address space.) This makes them candidates for optimal allocation, a common reason for declaring registers; but it also makes them candidates for more aggressive optimization.

+10
May 26 '16 at 16:31
source share



All Articles