Does C++ guarantee that offsetof(U, m)
always returns zero for any union U
and its member m
or are there cases when it's non-zero?
union U {
M m;
...
};
It evaluates to the offset (in bytes) of a given member within a struct or union type, an expression of type size_t. @0.sh : and if you read the answer in the question I linked, you'll find that all members in a union are at offset 0.
offsetof (type,member) Return member offset. This macro with functional form returns the offset value in bytes of member member in the data structure or union type type.
Description. The C library macro offsetof(type, member-designator) results in a constant integer of type size_t which is the offset in bytes of a structure member from the beginning of the structure. The member is given by member-designator, and the name of the structure is given in type.
Use offsetof() to find the offset from the start of z or from the start of x . #include <stddef. h> size_t offsetof(type, member); offsetof() returns the offset of the field member from the start of the structure type.
Yes, it's always zero. 6.8.2.4:
Two objects a and b are pointer-interconvertible if:
— they are the same object, or
— one is a union object and the other is a non-static data member of that object ([class.union]), or
— one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, any base class subobject of that object ([class.mem]), or
— there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.
If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_cast. [Note: An array object and its first element are not pointer-interconvertible, even though they have the same address. — end note]
Since they are pointer-interconvertible and share the same address, offsetof(U, m)
should be zero.
Update:
If the union U
is not standard-layout, it's conditionally-supported. 17.2.4.1:
The macro offsetof(type, member-designator) has the same semantics as the corresponding macro in the C standard library header <stddef.h>, but accepts a restricted set of type arguments in this document. Use of the offsetof macro with a type other than a standard-layout class ([class.prop]) is conditionally-supported.183 The expression offsetof(type, member-designator) is never type-dependent and it is value-dependent if and only if type is dependent. The result of applying the offsetof macro to a static data member or a function member is undefined. No operation invoked by the offsetof macro shall throw an exception and noexcept(offsetof(type, member-designator)) shall be true.
But once it be supported, the only result make sense is zero since they share the same address.
There is only a guarantee of this if your union is standard-layout:
[class.mem/26]
: If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member if that member is not a bit-field. [..]
This is okay, because if it isn't standard-layout, you probably don't want to be using offsetof
anyway:
[support.types.layout/1]
: Use of theoffsetof
macro with a type other than a standard-layout class ([class.prop]) is conditionally-supported.
(It has undefined behaviour in C, and until C++17.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With