offsetof
|
Определено в заголовочном файле
<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) |
|
|
(C++11)
|
проверяет, является ли тип
стандартным размещением
(шаблон класса) |
|
документация C
для
offsetof
|
|