offsetof
Определено в заголовочном файле <cstddef> | ||
|---|---|---|
#define offsetof(type, member) /* implementation-defined */ |
Макрос offsetof расширяется до целочисленной константы типа std::size_t, значение которой — это смещение в байтах от начала объекта заданного типа к его заданному подобъекту, включая биты заполнения, если таковые имеются.
Для объекта o типа type со статической длительностью хранения o.member должно быть константным выражением-ссылкой на подобъект o. В противном случае поведение не определено. В частности, если member является статическим членом данных, полем битов или членом-функцией, поведение не определено.
Если type не является типом POD(до C++11)типом стандартного расположения(с C++11), результат offsetof не определён(до C++17)использование макроса offsetof условно поддерживается(с C++17).
Выражение offsetof(type, member) никогда не является зависимым от типа и является зависимым от значения только тогда, когда type зависит от типа.
Исключения
offsetof не генерирует исключения.
| Выражение | (с C++11) |
Примечания
| Смещение первого члена типа стандартного расположения всегда равно нулю (оптимизация пустого базового класса обязательна). | (с 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 | Применён к | Поведение, как опубликовано | Корректное поведение |
|---|---|---|---|
| CWG 273 | C++98 |
offsetof может не работать, если унарный operator& перегружен | требуется работать корректно даже если operator& перегружен |
| LWG 306 | C++98 | поведение не было определено, когда type не является типом POD | результат не определён в этом случае |
| LWG 449 | C++98 | другие требования к offsetof былиудалены решением LWG issue 306 | они были добавлены обратно |
См. также
целого типа без знака, возвращаемого оператором sizeof (typedef) |
|
|
(C++11) | проверяет, является ли тип типом стандартного расположения (шаблон класса) |
C документация по offsetof |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/types/offsetof