Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing struct member by address

Tags:

c

pointers

struct

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?

like image 416
Jack Avatar asked Dec 11 '22 19:12

Jack


2 Answers

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.

like image 171
Sergey Kalinichenko Avatar answered Dec 21 '22 18:12

Sergey Kalinichenko


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_ts 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. :)

like image 25
Dolda2000 Avatar answered Dec 21 '22 17:12

Dolda2000