我可以在不知道其中其他元素的情况下访问第一个结构体元素吗?

问题描述 投票:0回答:1

根据 ANSI,我怀疑这是 UB,但在我的系统(x64 Linux)上,即使使用

-Wall -Wextra -Werror -O3
gcc
clang
都会在这里产生预期的结果:

#include <stdio.h>

typedef struct {
        int tag;
} base;

typedef struct {
        base b;
        int x;
} derived1;

typedef struct {
        base b;
        int x, y;
} derived2;

int sum(void* p) {
        base* b = (base*)p;

        if(b->tag) {
                derived2* d = (derived2*)b;
                return d->x + d->y;
        }
        else {
                derived1* d = (derived1*)b;
                return d->x;
        }
}

int main(void) {
        derived1 d1;
        d1.b.tag = 0;
        d1.x = 2;

        derived2 d2;
        d2.b.tag = 1;
        d2.x = 3;
        d2.y = 4;

        printf("%d %d\n", sum(&d1), sum(&d2));
}

根据 ANSI,这是 UB 吗?

gcc
clang
也是UB吗?

如果我使用

-fno-strict-aliasing
或其他选项怎么办?

c gcc clang
1个回答
0
投票

定义该行为是因为 C 2018 6.7.2.1 15 说“...指向结构对象的指针,经过适当转换,指向其初始成员...”因为

sum
传递了指向
derived1
derived2
的指针,尽管转换为
void *
,并将其转换为
base *
,它是
derived1
derived2
的初始成员,结果是指向该初始成员的正确指针。 (迂腐地说,C 标准没有定义“适当转换”,但接受这个转换序列作为适当转换并没有争议。)

© www.soinside.com 2019 - 2024. All rights reserved.