Re: offsetof



On 30 Sep 2005 02:17:50 -0700, luke wrote:

>hi all,
>i have another question.
>I've read the FAQ regarding my former question (sizeof struct and
>union) and in question 2.14 it talks about offset macro.
>
>#define offsetof(type, mem) ((size_t) \
> ((char *)&((type *)0)->mem - (char *)(type *)0))
>
>Can anyone explain me how it works.
>1)I can't understand what "0" casted to (type *) means
>2)Isn't the second menber of substraction "(char *)(type *)0" useless?

Well ... 0 casted to type * means this ...

The C language allows you to convert an integer to a pointer or a
pointer to an integer. The result of doing this is "implementation
defined" but as the C99 standard says
<quote>
The mapping functions for converting a pointer to an integer or an
integer to a pointer are intended to be consistent with the addressing
structure of the execution environment.
<end quote>

The idea being that you can convert the address of an object to an
integer and get sensible values e.g. if you have
char abc[16];
and abc is at physical address 0xFFFF0000 in memory, then
(int)&abc[0]
would most likely give you a value of 0xFFFF0000
and
(int)&abc[1] would give you 0xFFFF0001

One use for this is that if you need to read or write to a physical
location in memory you can do it like this
*(char*)0xFFFF0000 = 0x55;
On many machines, this would have the effect of setting abc[0] to 0x55.

Hence when you cast zero to (type *) you are converting an integer to a
pointer as if you have an object whose address is at physical location
0x00000000.
Then when you write &((type *)0)->mem you are taking the address of the
mem member of the fictitious object whose address is zero. When you
subtract the address of the start of the fictitious object ( (char
*)(type *)0) from the address of the mem member, you get its offset as
an integer (the exact type of the integer is ptrdiff_t)

The casts to char* are necessary so that the type of the two pointers
being subtracted are both char* giving the offset of the mem member in
units of char.

The expression (type*)0 does NOT create a NULL pointer constant unless
the type of "type" is void i.e. it is (void*)0.

darkknight
.



Relevant Pages

  • Re: using a freed pointer
    ... char *p1 = malloc; ... Consider a platform that has separate data and address registers. ... the passed-in pointer from the address space. ... offset 0xff00 is greater than the offset 0x0010. ...
    (comp.lang.c)
  • Re: sizeof a relative pointer in a struct
    ... But you are not getting the size of a pointer, ... you get 4 if you apply sizeof to a pointer, ... char blings; ... know the offset of the variable... ...
    (comp.lang.c)
  • Re: two dimensional arrays:
    ... > Now I can't see how a pointer could be a different size for one type VS ... pointer plus the offset of the byte within the word. ... Types void* and char* have the same size but ...
    (comp.lang.c)
  • Valid Function Pointer Casting
    ... I need a macro to compute an offset of an object relative to a base ... The problem is the object can sometimes be a function pointer ... to function returning void", is being converted to "pointer to char". ...
    (comp.lang.c)
  • Re: Problem with va_ macros and arrays of arrays
    ... > the arrays passed to a ... > specific char, somewhat similar to what the standard function ... that with an array of struct, or possibly a pointer to a dynamic array ... > As I'm still a beginner in C without a copy of the standard I ...
    (comp.lang.c)