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 не выбрасывает исключений.
| Выражение | (начиная с 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 не является PODType | в этом случае результат не определён |
| 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/cpp/types/offsetof