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

offsetof

Материал из cppreference.com
< cpp‎ | types
 
 
Библиотека метапрограммирования
Свойства типов
Категории типов
(C++11)
(C++14)  
(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++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
(определение типа)[править]
проверяет, является ли тип типом со стандартной компоновкой
(шаблон класса)[править]
close