有结构
typedef struct _pack_t {
char tag[4];
int type;
size_t size;
size_t offset;
char data[0];
} __attribute__((packed)) pack_t;
并且有一个定义
#define PACK_OFFSET ((size_t)((pack_t *)0)->data)
这个定义是什么意思?以及如何理解指针“0”?
答案 0 :(得分:4)
这是一个预处理器宏。它产生data
结构的pack_t
成员的偏移量。当它的封闭结构的基地址为零时,取这个成员的绝对地址。
使用非NULL指针,这可以通过声明类型pack_t
的任何变量然后获取结构的地址和成员的地址(以字节为单位)的差异来完成,如下所示:
pack_t dummy;
size_t offset = (char *)&dummy.data - (char *)&dummy;
(但不仅这是无效的,因为减去的两个指针不指向同一个数组的元素,但它也需要一个多余的局部变量,由于各种原因不需要。这就是为什么这是巧妙的使用空指针实现。)
(不要因为没有看到{({1}})运算符的地址而感到困惑 - &
是一个数组类型,因此它会衰减成指向其第一个元素的指针。)
答案 1 :(得分:3)
您struct _pack_t
中字段数据的偏移量;
(pack_t *) 0
是类型为pack_t的NULL指针。
请注意,字段数据具有0长度,意味着变量':它必须由某个函数填充..
ex:memcpy((char *) packet + PACK_OFFSET, data, data_len);
答案 2 :(得分:1)
让我们想象一下黑板
老师看到的地方
PACK_OFFSET
(s)他将橡皮布拉出并擦掉PACK_OFFSET
并用
((size_t)((pack_t *)0)->data)
答案 3 :(得分:1)
我没有回答你的问题,我只举一个例子来支持H2CO3意见。为了正确获得结构成员的偏移量,它必须是0指针。这是代码:
typedef struct _pack_t {
char tag[4];
int type;
size_t size;
size_t offset;
char data[0];
}pack_t;
#define OFFSET_0 ((size_t)((pack_t *) 0)->data)
#define OFFSET_1 ((size_t)((pack_t *) 1)->data)
#define OFFSET_2 ((size_t)((pack_t *) 2)->data)
int main(void){
printf("%lu\n", OFFSET_0);
printf("%lu\n", OFFSET_1);
printf("%lu\n", OFFSET_2);
return 0;
}
输出:
24
25
26