Consider a struct with two members of integer type. I want to get both members by address. I can successfully get the first, but I'm getting wrong value with the second. I believe that is garbage value. Here's my code:
#include <stdio.h>
typedef struct { int a; int b; } foo_t;
int main(int argc, char **argv)
{
foo_t f;
f.a = 2;
f.b = 4;
int a = ((int)(*(int*) &f));
int b = ((int)(*(((int*)(&f + sizeof(int))))));
printf("%d ..%d\n", a, b);
return 0;
}
I'm getting:
2 ..1
Can someone explain where I've gone wrong?
The offset of the first member must always be zero by the C standard; that's why your first cast works. The offset of the second member, however, may not necessarily be equal to the size of the first member of the structure because of padding.
Moreover, adding a number to a pointer does not add the number of bytes to the address: instead, the size of the thing being pointed to is added. So when you add sizeof(int)
to &f
, sizeof(int)*sizeof(foo_t)
gets added.
You can use offsetof
operator if you want to do the math yourself, like this
int b = *((int*)(((char*)&f)+offsetof(foo_t, b)));
The reason this works is that sizeof(char)
is always one, as required by the C standard.
Of course you can use &f.b
to avoid doing the math manually.
Your problem is &f + sizeof(int)
. If A
is a pointer, and B
is an integer, then A + B
does not, in C, mean A
plus B
bytes. Rather, it means A
plus B
elements, where the size of an element is defined by the pointer type of A
. Therefore, if sizeof(int)
is 4 on your architecture, then &f + sizeof(int)
means "four foo_t
s into &f
, or 4 * 8 = 32 bytes into &f
".
Try ((char *)&f) + sizeof(int)
instead.
Or, of course, &f.a
and &f.b
instead, quite simply. The latter will not only give you handy int
pointers anyway and relieve you of all those casts, but also be well-defined and understandable. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With