我不确定代码中是否存在指针别名(或其他标准符合性问题)在断言转换中。似乎一个指向联合类型的指针可以被强制转换为第一个成员的指针,由于联合体仅由这两个结构组成,我认为强制转换到第一个成员应该能够工作,但我不确定这是否正确,或者我是否在过程中忽略了填充细节。联合体是否需要填充上位位?
这似乎是未指明的行为?是否有人知道是否支持这种行为?我知道有一种替代标准的方法是使用一个带有枚举类型
字段和struct container_storage
成员的结构体,但考虑到这些信息已经在struct contained
中,这似乎是浪费空间。
Linux下的编译命令:gcc -std=c99 -Wextra -pedantic -fstrict-aliasing test.c && ./a.out && echo $?
返回0
#include <stdlib.h>
#include <assert.h>
enum type {type_a = 1, type_b = 2};
struct contained {
int some_other_field;
enum type type;
};
struct container_a {
struct contained contained;
int test;
};
struct container_b {
struct contained contained;
char test;
};
union container_storage {
struct container_a container_a;
struct container_b container_b;
};
int
main(int argc, char **argv)
{
union container_storage a =
{.container_a = {.contained = {.type = type_a}, .test = 42}};
union container_storage b =
{.container_b = {.contained = {.type = type_b}, .test = 'b'}};
assert(((struct contained *)&a)->type == type_a);
assert(((struct contained *)&b)->type == type_b);
return EXIT_SUCCESS;
}
参考资料:
assert
中的cast是否是良定义的,如果将其转换为struct contained *
是良定义的,则->type
就是良定义的,但如果转换不是良定义的,则共同初始序列规则无法帮助。共同初始序列规则使得a
和b
上的->container_a.contained.type
和->container_b.contained.type
都是有效访问(但值得注意的是,这个保证并不能防止联合体具有前导填充 - 关于转换它们的指针的单独保证才能做到这一点)。 - mtraceur