当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
你有任何恐怖故事要讲吗?GCC手册最近添加了一个关于-fstrict-aliasing的警告并通过联合转换指针:
[...]获取地址,强制生成指针并取消引用结果具有未定义的行为 [强调添加],即使转换使用了联合类型,例如:
union a_union {
int i;
double d;
};
int f() {
double d = 3.0;
return ((union a_union *)&d)->i;
}
Run Code Online (Sandbox Code Playgroud)
有没有人有一个例子来说明这种未定义的行为?
请注意,这个问题不是关于C99标准所说或不说的.它是关于gcc和其他现有编译器的实际功能.
我只是猜测,但一个潜在的问题可能在于设置d为3.0.因为d是永远不会直接读取的临时变量,并且永远不会通过"稍微兼容"的指针读取,所以编译器可能不会费心去设置它.然后f()将从堆栈中返回一些垃圾.
我的简单,天真,尝试失败了.例如:
#include <stdio.h>
union a_union {
int i;
double d;
};
int f1(void) {
union a_union t;
t.d = 3333333.0;
return t.i; // gcc manual: 'type-punning is allowed, provided...' (C90 6.3.2.3)
}
int f2(void) {
double d = 3333333.0;
return ((union a_union *)&d)->i; // gcc …Run Code Online (Sandbox Code Playgroud) 说我有以下类型:
typedef struct TYPEA
{
int type;
char[12] id;
} TYPEA;
typedef struct TYPEB
{
int type;
int value;
} TYPEB;
Run Code Online (Sandbox Code Playgroud)
我想使用创建这些类型和'int'的联合,这样我就可以访问"type"int而无需知道TYPEA或TYPEB是否存储在union中(int的值让我确定实际存储的是哪个那里).虽然我无法获得正确的语法.
我的工会:
typedef union MEMBER
{
int type;
struct TYPEA a;
struct TYPEB b;
} MEMBER;
Run Code Online (Sandbox Code Playgroud)
通过以下方式访问联盟:
typedef struct WRAPPER
{
union MEMBER* member;
struct WRAPPER* next;
} WRAPPER;
Run Code Online (Sandbox Code Playgroud)
问题:
w->member->a.id会在某些结构或联合中提供"成员'id'请求.谢谢.