39

I'm looking for a piece of code that can tell me the offset of a field within a structure without allocating an instance of the structure.

IE: given

struct mstct {
    int myfield;
    int myfield2;
};

I could write:

mstct thing;
printf("offset %lu\n", (unsigned long)(&thing.myfield2 - &thing));

And get offset 4 for the output. How can I do it without that mstct thing declaration/allocating one?

I know that &<struct> does not always point at the first byte of the first field of the structure, I can account for that later.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
davenpcj
  • 12,508
  • 5
  • 40
  • 37

3 Answers3

73

How about the standard offsetof() macro (in stddef.h)?

Edit: for people who might not have the offsetof() macro available for some reason, you can get the effect using something like:

#define OFFSETOF(type, field)    ((unsigned long) &(((type *) 0)->field))
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 1
    Not quite what I wanted, because I don't have stddef.h, but it does answer my question with: #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) – davenpcj Sep 26 '08 at 21:21
  • 4
    Wow - no stddef.h? Just out of curiosity, could I ask what you're using? – Michael Burr Sep 26 '08 at 21:25
  • 1
    It's in the C99 standard, so I'd suggest getting a new compiler. – wnoise Sep 26 '08 at 21:27
  • 1
    more than that - it's been in C since ANSI C89. I have no idea how common (or uncommon) it was pre-standard. – Michael Burr Sep 26 '08 at 21:29
  • I once had a C compiler that had offsetof() defined in stddef.h with the zero trick, but it also didn't allow the use of zero as a base address. (Long time ago - 1989, or thereabouts.) Workaround was to change 0 to 1024 instead. – Jonathan Leffler Sep 27 '08 at 05:17
9

Right, use the offsetof macro, which (at least with GNU CC) is available to both C and C++ code:

offsetof(struct mstct, myfield2)
Dan Lenski
  • 76,929
  • 13
  • 76
  • 124
  • offsetof() has been in standard C/C++ since the first ANSI C89 standard. Every compiler should have it, unless you're using something seriously ancient. Even then it could be cobbled together using ugly casting & pointer arithmetic. – Michael Burr Sep 26 '08 at 21:23
  • Agreed - I'd most likely provide a dummy to provide that macros. Plauger provides "The Standard C Library" and it is an easy header to provide - as long as it does not have to be portable. – Jonathan Leffler Sep 27 '08 at 05:19
  • AFAIK, offsetof() is not hing *but* ugly casting & pointer arithmetic... something like: #define offsetof(type, field) ((char *)&(((type *)0)->field) - (char *)0) – Dan Lenski Oct 01 '08 at 00:53
3

printf("offset: %d\n", &((mstct*)0)->myfield2);

Frank Krueger
  • 69,552
  • 46
  • 163
  • 208
  • 1
    Apart from the fact that `offsetof` does this in a more readable way, you can't generally print a `ptrdiff_t` with `%d` -- on LP64 systems, it's too large. – Fred Foo Feb 03 '13 at 15:08