Namespaces
Variants

offsetof

From cppreference.net
Utilities library
Определено в заголовочном файле <cstddef>
#define offsetof(type, member) /* implementation-defined */

Макрос offsetof раскрывается в целочисленное константное выражение типа std::size_t , значение которого представляет собой смещение в байтах от начала объекта указанного типа до его указанного подобъекта, включая биты заполнения , если они присутствуют.

Для объекта o типа type со статической продолжительностью хранения, o. member должно быть lvalue константным выражением, ссылающимся на подобъект o . В противном случае поведение не определено. В частности, если member является статическим членом-данных , битовым полем или функцией-членом , поведение не определено.

Если type не является PODType (до C++11) стандартным-расположением типом (начиная с C++11) , результат offsetof не определён (до C++17) использование макроса offsetof условно поддерживается (начиная с C++17) .

Выражение offsetof ( type, member ) никогда не является зависимым по типу и является зависимым по значению тогда и только тогда, когда type является зависимым.

Содержание

Исключения

offsetof не генерирует исключений.

Выражение noexcept ( offsetof ( type, member ) ) всегда вычисляется в true .

(начиная с C++11)

Примечания

Смещение первого члена стандартно-компонуемого типа всегда равно нулю ( оптимизация пустого базового класса является обязательной).

(since C++11)

offsetof не может быть реализован в стандартном C++ и требует поддержки компилятора: GCC , LLVM .

member не ограничивается прямым членом. Он может обозначать подобъект заданного члена, такой как элемент члена-массива. Это указано в C DR 496 .

В стандарте C23 указано, что определение нового типа, содержащего непомещенную в скобки запятую в offsetof , является неопределенным поведением, и такая практика обычно не поддерживается реализациями в режимах C++: offsetof ( struct Foo { int a, b ; } , a ) отвергается всеми известными реализациями.

Пример

#include <cstddef>
#include <iostream>
struct S
{
    char   m0;
    double m1;
    short  m2;
    char   m3;
//  private: int z; // warning: 'S' is a non-standard-layout type
};
int main()
{
    std::cout
        << "offset of char   m0 = " << offsetof(S, m0) << '\n'
        << "offset of double m1 = " << offsetof(S, m1) << '\n'
        << "offset of short  m2 = " << offsetof(S, m2) << '\n'
        << "offset of char   m3 = " << offsetof(S, m3) << '\n';
}

Возможный вывод:

offset of char   m0 = 0
offset of double m1 = 8
offset of short  m2 = 16
offset of char   m3 = 18

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
CWG 273 C++98 offsetof может не работать, если унарный operator& перегружен требуется корректная работа даже
если operator& перегружен
LWG 306 C++98 поведение не было определено, когда type не является PODType результат не определён в этом случае
LWG 449 C++98 другие требования к offsetof были
удалены решением LWG issue 306
возвращены обратно

Смотрите также

беззнаковый целочисленный тип, возвращаемый оператором sizeof
(typedef)
проверяет, является ли тип стандартным размещением
(шаблон класса)