Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is offsetof of a union member always zero?

Tags:

c++

union

unions

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;
  ...
};
like image 326
vitaut Avatar asked Jul 31 '20 22:07

vitaut


People also ask

Is offset of each member in union is zero?

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.

What does offsetof return c++?

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.

What is offsetof function in C?

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.

How do you find the offset of a structure member?

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.


2 Answers

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.

like image 149
yao99 Avatar answered Sep 29 '22 10:09

yao99


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 the offsetof 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.)

like image 20
Asteroids With Wings Avatar answered Sep 30 '22 10:09

Asteroids With Wings