-1

This is a query in continuity with my last query

I was trying to execute the following code in gdb :

struct t {} ;
struct s {int a, b, c, d, e, f, g, h, i, j ;} ;
register int aa __asm__("esi") ;
void f(register int a) {}

main() {
    register int x=1291;
    register int arr[10] ={1,2,3};
    register int y = 8 ;
    register int a = 8, b = 78 ;
    int xx = 90 ;
    register struct t tvar; //, *tp = &tvar ;
    register struct s var ; //, *sp = &var;
    xx = x ;
    xx = a ;
    xx = y ;
}

Now in gdb the results are as follows :

(gdb) p &x
$1 = (int *) 0xbffff17c
(gdb) p &y
Address requested for identifier "y" which is in register $ebx
(gdb) p &a
Address requested for identifier "a" which is in register $edi
(gdb) p &b
Can't take address of "b" which isn't an lvalue.
(gdb) p a
$2 = 8
(gdb) p b
$4 = <optimized out>
(gdb) p &tvar
$5 = (struct t *) 0xbffff1df
(gdb) p &var
$6 = (struct s *) 0xbffff1b0

Now address of tvar, var and arr show that the register request has been ignored by compiler for array and structure variables (I hope I am right) But why is address of x displayed. Also why does it say Can't take address of "b" which isn't an lvalue And why does print b show $4 = optimized out

I fail to understand what is actually happening

Community
  • 1
  • 1
user3282758
  • 1,379
  • 11
  • 29
  • register is AFAIK a hint for the compiler and it is in no way forced to do so, so I would say this is expected behaviour... – Mario The Spoon Jul 30 '15 at 17:27
  • 1
    @MarioTheSpoon: It's a bit more than a hint, insofar as I believe *compilers* are required to refuse attempts to take the address of variables declared *register*. The debugger, however, is not a compiler. If the compiler judges that storing something in memory would be more efficient than keeping it in a register; in that situation, the compiler would not be allowed to make the address available to the code, but since the behavior of the debugger falls outside the jurisdiction of the C standard, nothing would forbid the address from being made available to the debugger. – supercat Jul 30 '15 at 17:30
  • @supercat have not thought on that aspect, but of course you are right! – Mario The Spoon Jul 30 '15 at 19:01
  • `register` on an array will eventually be ignored for most architectures. How do you actually expect indexing work for such? Similar for `struct`s. – too honest for this site Jul 30 '15 at 19:52
  • @Olaf my question was never 'why is it ignored for struct or array'. My question was rather why it seems to be ignored for one int type var and not for other int type var – user3282758 Jul 31 '15 at 03:16
  • So why do you actually expect it to be ignored for arrays and structs, but not for arrays? Sounds illogical to me. – too honest for this site Jul 31 '15 at 03:21
  • @Olaf for the same reason you yourself have given in your previous comment – user3282758 Jul 31 '15 at 07:47
  • sorry, "but not for arrays" should have been "not for scalars" – too honest for this site Jul 31 '15 at 12:41

3 Answers3

2

The register keyword has always (since Unix v6 release May 1975) been regarded as a suggestion and not anything the compiler has to obey. It came from a time when it was more traditional to expect programmers to optimize code rather than the compiler.

Modern (that is, since 1985 or so) compilers generally optimize variables into registers much better than most programmers would. Unless you thoroughly understand code generation strategy, it is best to omit register.

It is, of course, illegal to attempt taking the address of a register variable. A non-register variable which is not taken the address may be placed in a register.

Also why does it say Can't take address of "b" which isn't an lvalue And why does print b show $4 = optimized out

b is never used and therefore does not participate in the algorithm, so the compiler eliminated it.

wallyk
  • 56,922
  • 16
  • 83
  • 148
  • There is actually one useful effect of `register`: you cannot take the address of such a variable. So you can protect such a variable against being passed to functions by address. – too honest for this site Jul 30 '15 at 19:47
2

Given register int x;, a compiler would be required to forbid any effort by the C program to take the address of x. The behavior of debuggers like gdb, however, falls outside the jurisdiction of the C standard. If a variable happens to be stored in memory at some point during a program's execution, it might not be legal for code using that variable to find out what its address is, but nothing would forbid a compiler making that information available to a debugger, or a debugger from making that information available to a programmer.

Note that with some compilers, it is entirely possible that a variable's address might not be constant throughout its lifetime. If a variable is used in two disjoint parts of a function, and the compiler can determine that its value won't be read in either part of the function without having been written in the same part, the compiler may decide to create two variables of the same name and nominal scope which have independent but non-overlapping lifetimes. If a compiler performs such optimizations, a request to print the variable's address while one part of the function is running might print out a different address from a request to print its address while another part is running. If C code takes the address of a variable, the variable isn't supposed to move unless or until execution leaves the scope where it is defined. Displaying a variable's address within the debugger, however, imposes no such restriction.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

According to the C standard, compilers are free to choose whether they will keep a register variable actually in register or not. So, even if you mention register before a variable definition, its not assured that it will be stored in a register and not regular memory address.. All that does is, gives a hint to the compiler that the variable will be heavily used.

Thats why you are able to take the address of some variable and not of others.

Haris
  • 12,120
  • 6
  • 43
  • 70