Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The offsetof() macro is defined by the C Standard as a portable way to determine the offset, expressed in bytes, from the start of the object to a given member of that object. The C Standard, subclause 7.17, paragraph 3 [ISO/IEC 9899:1999], specifies, in part in part, specifies the following:

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

...

When specifying the type argument for the offsetof() macro, only pass a only a standard-layout class. The full description of a standard-layout class can be found in paragraph 7 of the [class] clause of the C++ Standard, or the type can be checked with the std::is_standard_layout<> type trait. When specifying the member designator argument for the offsetof() macro, do not pass a bit-field, static data member, or function member. Passing an invalid type or member to the offsetof() macro is undefined behavior.

...

In this noncompliant code example, a type that is not a standard-layout class is passed to the offsetof() macro, resulting in undefined behavior:.

Code Block
bgColor#FFcccc
langcpp
#include <cstddef>
 
struct D {
  virtual void f() {}
  int i;
};
 
void f() {
  size_t off = offsetof(D, i);
  // ...
}

...

It is not possible to determine the offset to i within D because D is not a standard-layout class. However, it is possible to make a standard-layout class within D if this functionality is critical to the application, as demonstrated by this compliant solution:.

Code Block
bgColor#ccccff
langcpp
#include <cstddef>

struct D {
  virtual void f() {}
  struct InnerStandardLayout {
    int i;
  } inner;
};

void f() {
  size_t off = offsetof(D::InnerStandardLayout, i);
  // ...
}

...

Because static data members are not a part of the class layout, but are instead an entity of their own, this compliant solution passes the address of the static member variable as the buffer to store the data into in and passes 0 as the offset:.

Code Block
bgColor#ccccff
langcpp
#include <cstddef>
 
struct S {
  static int i;
  // ...
};
int S::i = 0;
 
extern void store_in_some_buffer(void *buffer, size_t offset, int val);
 
void f() {
  store_in_some_buffer(&S::i, 0, 42);
}

...