Wednesday, January 6, 2010

C Structures: Calculating offset of an element

Let's say we have the following structure:

int a;
char c;
} example;

To calculate offset of 'c', we have following ways:

1. Use the macro offsetof() defined in header file stddef.h.
unsigned int x = offsetof(struct example, c);
This macro takes care of padding of elements done by the compiler.

2. Other way to get the offset f c is:
// C snippet
example var, example *ptr;
ptr = &var;
offset = &(ptr->c)- &(ptr->a)

------|base_addr = 0x0000
int a |
------|addr = (0x0000 + 0x0004)
int c |
------|addr = (0x0004 + 0x0004)

We are getting the distance of 'c' from base of the structure. So, address &(ptr->c) should be calcuated by compile as: base_address of var + distance of 'c' from base
If we somehow set base_addr as zero, we will get the offset i.e. 0x0004.

A hack to accomplish this result is as follows:
#define POINTER = ((struct example*)(0))
unsigned int x = (unsigned int) & (POINTER->c);

We are typecasting an address '0' pointing to a type of data 'struct example'.
Now when you do (x)->c, it is equivalent to: BASE_ADDESS(x) + size_of_data elements preceding 'c'. We are tricking the compiler by giving BASE_ADDRESS as zero.

This hack may be incorrect if element padding is done by the compiler.

No comments: