Консультация № 142074
24.08.2008, 08:07
0.00 руб.
0 1 1
Уважаемые эксперты, в одном источнике увидел как написан макрос для определения смещения члена структуры в байтах.
Код:
 #define	offsetof(type, mem) ((size_t) ( (char *)&((type *) 0)->mem - (char *)((type *) 0))) 

Поясните, пожалуйста, смысл: нулевой указатель здесь преобразуется к типу type ? Что это дает?

Обсуждение

давно
Советник
165461
578
24.08.2008, 10:43
общий
24.08.2008, 11:27
это ответ
Здравствуйте, Warobushek!

Если бы по нулевому адресу находилась структура типа type ,
то все, наверное, было бы понятно:

(char*)(type*) 0 - адрес структуры, т.е. начала области памяти, отведённой под неё.
&((char*)((type*) 0 -> mem)) - адрес её элемента mem ,
и, соответственно, смещение вычисляется как разность этих адресов.

Компилятор интерпретирует содержимое памяти в соответствии с типом указателя.
Иначе говоря, он вычисляет положение элементов структуры на основании определения её типа,
и использует полученные адреса для доступа к элементам структуры.
При вычислении адресов неважно,что фактически находится в данной области памяти,
поэтому в макросе в качестве адреса структуры годится любой адрес, в том числе и нулевой.

Замечание.
Вместо (char*)(type*) 0 можно было бы написать просто (char*) 0 ,
но в выражении (type*)0->mem преобразование типа необходимо.
чтобы было известно, что 0 должен рассматриваться как адрес структуры определённого типа.

Пример использования макроса в приложении.

Приложение:
#include <stdio.h>

#define offset_of(type, mem) ((size_t) ((char *)&((type *) 0)->mem - (char *) 0))

typedef struct {
char x[10];
char y[2];
char z;
} A;

int main()
{
size_t x_offset, y_offset, z_offset;

x_offset = offset_of (A,x);
y_offset = offset_of (A,y);
z_offset = offset_of (A,z);

printf ("x: %u\n", x_offset);
printf ("y: %u\n", y_offset);
printf ("z: %u\n", z_offset);
return 0;
Форма ответа