比较结构指针、丢弃成员和 UB

tex*_*ral 4 c casting strict-aliasing void-pointers undefined-behavior

考虑以下代码:

int main()
{
    typedef struct { int first; float second; } type;

    type whole = { 1, 2.0 };
    void * vp = &whole;

    struct { int first; } * shorn = vp;
    printf("values: %d, %d\n", ((type *)vp)->first, shorn->first);
    if (vp == shorn)
        printf("ptrs compare the same\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

两个问题:

  1. 指针相等比较是UB吗?
  2. 关于second初始化行上的成员的“剪切” shorn:像这样抛弃结构成员然后取消引用操纵的指针以访问其余成员是否有效?

dbu*_*ush 5

将两个指针与==when 一个是 a 进行比较void *是明确定义的。

C 标准的第 6.5.9 节关于相等运算符的==说明如下:

2符合下列条件之一:

  • 两个操作数都有算术类型;
  • 两个操作数都是指向兼容类型的合格或不合格版本的指针;
  • 一个操作数是指向对象类型的指针,另一个是指向 的限定或非限定版本的指针void;或者
  • 一个操作数是指针,另一个是空指针常量

...

5否则,至少有一个操作数是一个指针。如果一个操作数是指针,另一个是空指针常量,则将空指针常量转换为指针的类型。 如果一个操作数是指向对象类型的指针,而另一个操作数是指向 的限定或非限定版本的指针void,则前者将转换为后者的类型。

之所以有效,shorn->first是因为指向结构的指针可以转换为指向其第一个成员的指针。对于type未命名结构类型和未命名结构类型,它们的第一个成员是 an,int所以它起作用了。