dgn*_*uff 7 c undefined-behavior unions language-lawyer type-punning
以下是现代C中未定义的行为:
union foo
{
int i;
float f;
};
union foo bar;
bar.f = 1.0f;
printf("%08x\n", bar.i);
Run Code Online (Sandbox Code Playgroud)
并打印1.0f的十六进制表示.
但是以下是未定义的行为:
int x;
printf("%08x\n", x);
Run Code Online (Sandbox Code Playgroud)
那这个呢?
union xyzzy
{
char c;
int i;
};
union xyzzy plugh;
Run Code Online (Sandbox Code Playgroud)
这应该是未定义的行为,因为没有plugh编写成员.
printf("%08x\n", plugh.i);
Run Code Online (Sandbox Code Playgroud)
但是这个呢.这是未定义的行为吗?
plugh.c = 'A';
printf("%08x\n", plugh.i);
Run Code Online (Sandbox Code Playgroud)
现在大多数C编译器都有sizeof(char) < sizeof(int),sizeof(int)或者是2或4.这意味着在这些情况下,最多plugh.i会写入50%或25%,但读取剩余的字节将读取未初始化的数据,因此应该是未定义的行为.在此基础上,是整个读取未定义的行为?
缺陷报告283:访问非当前联合成员("类型双关语")涵盖了这一点,并告诉我们如果存在陷阱表示,则存在未定义的行为.
缺陷报告问:
在对应于6.5.2.3#5的段落中,C89包含以下句子:
除了一个例外,如果在将值存储在对象的不同成员中之后访问union对象的成员,则该行为是实现定义的.
与此句相关的是这个脚注:
标量类型的"字节顺序"对于不会沉溺于类型处罚的独立程序是不可见的(例如,通过分配一个联合的一个成员并通过访问另一个成员,这是一个适当的六字形数组类型来检查存储) ,但必须在符合外部施加的存储布局时进行说明.
C99中唯一相应的措词是6.2.6.1#7:
当值存储在union类型的对象的成员中时,对象表示的不对应于该成员但对应于其他成员的字节采用未指定的值,但union对象的值不应因此而变为陷阱表示.
目前尚不清楚C99词语与C89词语具有相同的含义.
缺陷报告添加了以下脚注:
在6.5.2.3#3中将新脚注78a附加到"指定成员"一词:
78a 如果用于访问union对象内容的成员与上次用于在对象中存储值的成员不同,则该值的对象表示的相应部分将被重新解释为新类型中的对象表示形式如6.2.6所述(有时称为"打字"的过程).这可能是陷阱表示.
C11 6.2.6.1总则告诉我们:
某些对象表示不需要表示对象类型的值.如果对象的存储值具有这样的表示,并且由不具有字符类型的左值表达式读取,则行为是未定义的.如果这样的表示是由副作用产生的,该副作用通过不具有字符类型的左值表达式修改对象的全部或任何部分,则行为是未定义的.50) 这种表示称为陷阱表示.
| 归档时间: |
|
| 查看次数: |
320 次 |
| 最近记录: |