tags:

views:

105

answers:

3

Hi, in qemu source code, I have the following macro named offsetof. Can anybody tell me what it does?

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)

It's used in this manner :

offsetof(CPUState, icount_decr.u32)

where CPUState is a struct.

I think it gives the offset of the member inside a struct, but I'm not sure.

EDIT:Yeah, I found out what was happening. The definition of CPUState had a macro inside, which I missed, which included the variable icount_decr.

+1  A: 

Your thinking is correct! And the name of the macro gives a good hint, too. ;)

Dmitry Brant
+3  A: 

It gets the offset of the member of a struct. It does so by casting address zero to a struct of that type then taking the address of the member.

Amardeep
C/C++ compilers have lately been adding an intrinsic function for this, mainly because you can break this technique with overloaded operators in C++, but also because it *is* technically undefined behavior and you can imagine a sufficiently aggressive points-to optimization breaking it.
Zack
@Zack: It's a library feature, so no, it's not undefined behavior. An implementation is free to implement it however they want.
GMan
He's implying that this macro is defined inside an application program in which case it _is_ undefined behaviour (although extremely likely to work as expected of course). If the definition was in the standard library then it wouldn't be undefined of course.
John Burton
@John: If `offsetof` is indeed (re)defined by some library, they've made the program ill-formed by using a reserved identifier. They should use the one defined in the standard library.
GMan
I'm going to be incredibly hair-splitty and insist that "`((size_t) C++ is a little different).
Zack
@Zack: I hope you see I didn't recognize the macro was being redefined outside the standard library. And fair, though I doubt anything could get very far without eventually including `stddef.h`.
GMan
Yeah, I did see; I just felt like making microfibers ;-) FYI, in C, the standard headers are required to behave as-if they do not include each other, so you can actually get quite far without picking up stddef.h. (That's what I meant when I said C++ is a little different. I would have unpacked it but I ran out of characters.)
Zack
Zack
@Zack: Ah, good to know. I'm a C++ person, not a C person.
GMan
A: 

It's defined in §7.17/3:

offsetof(type, member-designator)
which expands to an integer constant expression that has type size_t, the value of which is the offset in bytes, to the structure member (designated by member-designator), from the beginning of its structure (designated by type). The type and member designator shall be such that given
static type t;
then the expression &(t.member-designator) evaluates to an address constant. (If the specified member is a bit-field, the behavior is undefined.)

Because the library doesn't have to necessarily follow language rules, an implementation is free to get the result however it pleases.

So the result of this particular implementation is not undefined behavior, because you aren't suppose to care how it's implemented. (In other words, your implementation makes the guarantee that taking the address of an indirection through a null pointer is well-defined. You of course can't assume this in your own programs.)

If that some library has (re)defined offsetof, they've made your program behavior undefined and should be using the standard library instead. (The dummies.)

GMan