Register variable address in C and C ++

I know the concept of a register variable and use it, but in my mind there are several questions based on what I tried.

  • I cannot access the address of the register variable in C, although I can do it in C ++! What for? Is there a problem with access to register variable addressing?

  • Suppose if I declare a string variable in C ++ as register, then where will this variable be stored? What is the point of declaring a storage class of non-numeric data types, such as a "string" in C ++, for registration?

UPDATE: I thought that C ++ allows us to get the address of the register variable, since I did not receive any errors in my program, which looks like this:

#include<iostream> #include<time.h> using namespace std; clock_t beg, en; int main(){ int j, k=0; beg=clock(); for(register int i=0;i<10000000;i++){ /*if(k==0){ cout<<&i<<endl; // if this code is uncommented, then C++ rejects the recommendation to make 'i' as register k++; }*/ } en=clock(); cout<<en-beg<<endl; cout<<&j<<endl<<&k; return 0; } 

I noticed that if I make the variable "i" registered and do not try to print the address using "& i", then C ++ will accept the recommendation and store the "i" in the register, this can be inferred from the working time of the for loop, which is always will be about 4-12 ms if "i" is in the register. But if I try to print the address of the variable "i", then although I do not get any errors, C ++ rejects the recommendation, and this can be done from the moment the loop is executed, which is always more than 25 if I am not registered!

So, basically I can’t get the address of a variable with a storage class as case in both C and C ++ !! Why?

+5
source share
7 answers

C and C ++ are different languages.

  • In C, you cannot take the address of a variable with a register store. Wed C11 6.7.1 / 6:

    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: an implementation can treat any register declaration simply as an auto declaration. [...]

  • In C ++, register is an obsolete, meaningless keyword that has no effect (except, perhaps, serves as a hint to the compiler), and variables declared as register still only have automatic storage. In particular, C ++ does not have a register class. (It just has a storage class specifier inherited from C.) Cf. C ++ 11, 7.1.1 / 3:

    A register specifier is a hint at the implementation that the declared variable will be heavily used. [Note: the hint can be ignored, and in most implementations it will be ignored if the variable address is accepted. This usage is deprecated [...]

Even in C, it is actually not guaranteed how the register store is implemented (implementations can freely handle register as auto ), but the language rules are applied independently.

+17
source

First, let's take a look at the relevant standards. It is always possible that C and C ++ have different meanings for this keyword.

C ++ 2011 Section 7.1.1 Paragraphs 2 and 3:

The register specifier applies only to variable names declared in block (6.3), or to function parameters (8.4). It indicates that the named variable has an automatic storage duration (3.7.3). A variable declared without a storage class specifier in the block area or declared as a function parameter defaults to automatic storage duration.

The register specifier is a hint at the implementation that the declared variable will be heavily used. [Note: the hint can be ignored, and in most implementations it will be ignored if the variable address is accepted. This use is deprecated (see D.2). - final note]

C 2011 Section 6.7.1 Paragraph 6 and footnote 121:

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

An implementation can handle any declaration in the register simply as an automatic declaration. However, regardless of whether address storage is actually used, the address of any part of the object declared using the register of the storage class specifier cannot be calculated either explicitly (using the unary and operator, as described 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 of the storage class specifier are sizeof and _Alignof.

So let me take what we learned here.

  • In C ++, the register keyword does not matter. It works like a compiler hint, but he suggested that most compilers would ignore this hint anyway.
  • In C, the register keyword stores a value. Here, for example, we cannot accept the address of the object (see the cited footnote). An implementation may ignore case hint and place the object into memory anyway, but the keyword limits what you can do with the object. These restrictions should allow the compiler to better optimize access to the object, but it is also possible (as suggested in the case of C ++) that the compiler will be able to do this anyway.

What do you see in practice:

  • We can understand why you get a syntax error in C when you try to take the register int address, so let's get around this.
  • You claim that you see a performance difference in C ++ depending on whether you use register . In this case, it would be nice to show your test, because there may be problems in the test itself. If the full test is in order, then it is certainly possible that your compiler uses a hint to get the best code.
  • The code you showed is definitely weird. This is because the compiler under optimization will most likely just remove the entire for loop from the code. The for loop has no side effects. It is likely (and will prefer) that the compiler will return identical code (that is, without code) with for (int i=0; i<100; ++i){} and for (register int i=0; i<100; ++i) {} .
+7
source

Taking the address of the variable, the FORCE compiler will save it in memory (if it is not an architect, where the registers have an address), I think that the TI 9900 series processors were implemented in this way, but this is undefined memory since 1984). If you told the compiler to use register , this makes it incompatible. Although the C ++ standard seems to suggest that the compiler does not have to tell you this, it can actually ignore the register keyword.

C ++ 11 draft n3337, section 7.1.1, bullet 3

The register specifier is a hint at the implementation that the declared variable 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). - final note]

(Edit: Yes, the TMS 9900 does have "registers in memory", so theoretically you can have a register address in this architecture, but the architecture is much larger than "registers live in memory (which has an address)," than "the registers have addresses ").

+3
source

The main answer is that on most architectures, general purpose registers do not have memory addresses. In general, a pointer is simply a (virtual) memory address of a memory cell containing an object. This is done for efficiency.

One could extend the concept of a pointer to a point in memory or register. However, this will reduce the speed of the program, since the code for dereferencing the pointer will need to check on what type of location the pointer is.

+1
source

Many aspects of C relate to the desire to allow single-pass compilation. Many early compilers read small source code, generated some compilation or machine code, forgot most of what they just read, read a little more code, generated some more assembly / machine codes, etc. If the compiler generates machine code, it may need to create a list of back patches for things like direct jumps, but the compiler can generate code for functions that were larger than its available RAM.

Many machines have several registers that can be used to store values, but the compiler cannot find out which variables could be most conveniently stored in registers at any given point in the code, unless it knows how the variables will be used later in the code . Given something like:

  void test(void) { int i,j,*p; p=&i; i=j=0; do { j++; *p+=10; j++; ... 

a single-pass compiler might not know if it can safely store j in a register through access to *p . Reset j to memory up to *p+=10; and reloading after it would deny most of the benefits of register allocation to it, but the compiler missed the reset and reload, but this code was followed by p=&j; he would have a problem. All passes of the loop after the first should contain j in memory when *p+=10; , but the compiler would have already forgotten the code that would be needed for the second pass.

This problem was resolved by indicating that if the compiler is declared register , the compiler can safely generate code that assumes that it will not be affected by pointers. The ban on receiving the address was IMHO unnecessarily excessive (*), but it was easier to describe than the one that would allow using the qualifier in more circumstances.

(*) Semantics would be useful even today if register promises that the compiler can safely store a variable in a register if it flushes it into memory when its address has been taken and is held upon reboot until the next time code used a variable forked back [via looping construct or goto] or entered a loop in which the variable was used].

+1
source

Precisely because it is a register. The address is the address of the memory location. If something is in the register, it is by definition not in the main memory.

0
source

In C, we cannot take the address of a variable with a register store. we need to save the name with a normal variable.

0
source

Source: https://habr.com/ru/post/1490595/


All Articles