自己的 offsetof 实现产生警告

Own offsetof implementation produces warning

我写了一小段代码来理解 offsetof 宏在后台是如何工作的。这是代码:

#include <stdio.h>   
#include <stdlib.h>  

int main(void)
{
    /* Getting the offset of a variable inside a struct */
    typedef struct {
        int a;
        char b[23];
        float c;
    } MyStructType;

    unsigned offset = (unsigned)(&((MyStructType * )NULL)->c);

    printf("offset = %u\n", offset);

    return 0;
}

但是,如果我 运行 它会收到一条警告消息:

警告:从指针转换为不同大小的整数 [-Wpointer-to-int-cast]

但是,如果我查看 c 中的原始 offsetof 宏,代码如下所示:

#include <stdio.h>   
#include <stdlib.h> 
#include <stddef.h> 

int main(void)
{
    /* Getting the offset of a variable inside a struct */
    typedef struct {
        int a;
        char b[23];
        float c;
    } MyStructType;

    unsigned offset = offsetof(MyStructType, c);

    printf("offset = %u\n", offset);

    return 0;
}

那么为什么我在转换为 unsigned 时会收到警告?它似乎是 offsetof 宏的类型。这让我很困惑。

正如 mch 评论的那样,unsigned 不是正确的类型;它在几乎所有现实世界的系统上都是 32 位的。 offsetof 宏应该产生类型为 size_t 的结果,这就是您要 "should" 转换到此处的结果。我认为您对将结果存储到 unsigned 类型的对象中的代码感到困惑;只要他们确定值很小就可以,但这并不意味着表达式 offsetof(MyStructType, c); 的类型是 unsigned。 C 允许您默默地将较大的整数类型分配给较小的整数类型。

但是,无论您做什么,这都不是 offsetof 的有效实现并且具有未定义的行为(通过将 -> 应用于无效指针)。在没有 UB 的情况下获得工作 offsetof 的方法是 #include <stddef.h>.