什么是“#define PACK_OFFSET((size_t)((pack_t *)0) - > data)”的意思

时间:2013-03-29 09:56:46

标签: c pointers c-preprocessor

有结构

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”?

4 个答案:

答案 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