Рубрики

Макрос OFFSETOF ()

Мы знаем, что элементы в структуре будут храниться в последовательном порядке их объявления.

Как извлечь смещение элемента в структуре? Мы можем использовать смещение макроса.

Обычно мы называем типы структур и объединений (или классы с тривиальными конструкторами ) как типы старых данных (POD), которые будут использоваться для объединения других типов данных . Следующий нестандартный макрос можно использовать для получения смещения элемента в байтах от базового адреса структурной переменной.

#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))

Ноль приводится к типу структуры, и к адресу необходимого элемента обращаются, который приводится к size_t . Согласно стандарту size_t имеет тип unsigned int . Общее выражение приводит к количеству байтов, после которых элемент помещается в структуру.

Например, следующий код возвращает 16 байтов (заполнение рассматривается на 32-битном компьютере) как смещение символьной переменной c в структуре Pod.

#include <stdio.h>

  
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))

  

typedef struct PodTag

{

   int     i;

   double  d;

   char    c;

} PodType;

  

int main()

{

   printf("%d", OFFSETOF(PodType, c) );

     

   getchar();

   return 0;

}

В приведенном выше коде следующее выражение будет возвращать смещение элемента c в структуре PodType .

OFFSETOF(PodType, c);

После стадии предварительной обработки указанный макрос расширяется до

((size_t)&(((PodType *)0)->c))

Поскольку мы рассматриваем 0 как адрес структурной переменной, c будет помещен после 16 байтов его базового адреса, то есть 0x00 + 0x10. Применение & к элементу структуры (в данном случае это c) возвращает адрес элемента, который равен 0x10. Преобразование адреса в unsigned int (size_t) приводит к количеству байтов, которые элемент помещает в структуру.

Примечание: мы можем рассмотреть адрес оператора & является избыточным. Без использования оператора адреса в макросе код отменяет ссылку на элемент структуры, размещенный по адресу NULL. Это вызывает исключение нарушения доступа (ошибка сегментации) во время выполнения.

Обратите внимание, что существуют другие способы реализации смещения макроса в соответствии с поведением компилятора. Конечная цель — извлечь смещение элемента. Мы увидим практическое использование смещения макроса в избранных списках для соединения похожих объектов (например, пула потоков) в другой статье.

Статья составлена Венки . Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Ссылки:

1. Код ядра Linux .

2. http://msdn.microsoft.com/en-us/library/dz4y9b9a.aspx

3. Документация по компилятору GNU C / C ++

Рекомендуемые посты:

Макрос OFFSETOF ()

0.00 (0%) 0 votes