Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

&((struct name *)NULL -> b) in printf statement [duplicate]

I found this code sample in a book, but I am unable to understand the expression in printf statement. and this program compiles successfully giving output as 4. kindly advise...

void main(){
    unsigned char c;

    typedef struct name {
      long a;
      int b;
      long c;
    }r;

    r re = {3,4,5};
    r *na=&re;

    printf("%d",*(int*)((char*)na + (unsigned int ) & (((struct name  *)NULL)->b)));
}
like image 292
Himanshu Sourav Avatar asked Nov 13 '14 09:11

Himanshu Sourav


1 Answers

Lets start from the last line:

printf("%d",*(int*)((char*)na + (unsigned int ) & (((struct name  *)NULL)->b)));

Lets interpret:

(unsigned int ) & ((    (struct name  *)NULL)->b )

Is actually casting & (( (struct name *)NULL)->b ) into a unsigned int.

& (( (struct name *)NULL)->b ) is the address (i.e it gives a pointer to):

((  (struct name  *)NULL)->b )

Which is actually the offset of b (as name.b) from NULL (0), which is 4 bytes (assuming a long is 4 bytes) and converted to a pointer of int, gives you 2 (assuming int is 2 bytes).

If instead of NULL it would have been a pointer to 0xFFFF0000, then &(ptr->b) would have been 0xFFFF0002. But it more like &(0 -> b) so its 0x00000002.

So, (unsigned int ) & (( (struct name *)NULL)->b ) == 2 (or maybe 1, or maybe 4, depending on the machine).

The rest is simple: *(int*)((char*)na + 2 will point to re->b. So it should print 4 (what have been initialized in the code, r re ={3,4,5};).

P.S: even if (unsigned int ) & (( (struct name *)NULL)->b ) != 2 (maybe it's 1, 4 or 8) - it should still print 4 because it then uses the same offset to get the value.

like image 67
Mark Segal Avatar answered Oct 02 '22 09:10

Mark Segal