Spec-Zone.ru › C++

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)

Примечания

Смещение первого члена типа стандартного размещения всегда равно нулю (оптимизация пустой базовой части обязательна).

(начиная с 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
добавлены обратно

См. также

size_t
беззнаковый целочисленный тип, возвращаемый оператором sizeof
(typedef)
is_standard_layout
(C++11)
проверяет, является ли тип типом стандартного размещения
(шаблон класса)
Документация по C для offsetof

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/types/offsetof

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API