Пространства имён
Варианты
Действия

offsetof

Материал из cppreference.com
< cpp‎ | types
 
 
Библиотека метапрограммирования
Свойства типов
Категории типов
(C++11)
(C++14)  
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Свойства типов
(C++11)
(C++11)
(C++14)
(C++11)
(C++11)(до C++20*)
(C++11)(устарело в C++20)
(C++11)
Константы свойств типа
Метафункции
(C++17)
Поддерживаемые операции
Запросы отношений и свойств
Модификации типов
(C++11)(C++11)(C++11)
Преобразования типов
(C++11)(устарело в C++23)
(C++11)(устарело в C++23)
(C++11)
(C++11)
(C++17)

(C++11)(до C++20*)(C++17)
Рациональная арифметика времени компиляции
Целочисленные последовательности времени компиляции
 
Определено в заголовочном файле <cstddef>
#define offsetof(type, member) /* определено реализацией */

Макрос 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)

[править] Примечание

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

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

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

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

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

[править] Пример

#include <cstddef>
#include <iostream>
 
struct S
{
    char   m0;
    double m1;
    short  m2;
    char   m3;
//  private: int z; // предупреждение: 'S' это нестандартный тип компоновки
};
 
int main()
{
    std::cout
        << "смещение char   m0 = " << offsetof(S, m0) << '\n'
        << "смещение double m1 = " << offsetof(S, m1) << '\n'
        << "смещение short  m2 = " << offsetof(S, m2) << '\n'
        << "смещение char   m3 = " << offsetof(S, m3) << '\n';
}

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

смещение char   m0 = 0
смещение double m1 = 8
смещение short  m2 = 16
смещение char   m3 = 18

[править] Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

Номер Применён Поведение в стандарте Корректное поведение
CWG 273 C++98 offsetof может не работать, если перегружен унарный operator& требуется для правильной работы, даже
если operator& перегружен
LWG 306 C++98 поведение не было указано, когда type не являлся PODType в этом случае результат не определён
LWG 449 C++98 другие требования offsetof были удалены решением
LWG проблема 306
добавлены обратно

[править] Смотрите также

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