offsetof
| Определён в заголовке <cstddef>
|
||
#define offsetof(type, member) /* implementation-defined */
|
||
Макрос offsetof раскрывается в целочисленное константное выражение типа std::size_t, значение которого представляет собой смещение в байтах от начала объекта указанного типа до указанного подобъекта, включая заполняющие биты, если таковые имеются.
Если дан объект o типа type со статической длительностью хранения, o.member должно быть lvalue-константным выражением, которое ссылается на подобъект o. В противном случае поведение не определено. В частности, если member является статическим элементом данных, битовым полем или функцией-членом, поведение не определено.
Если type не является POD-типом(до 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
|
|