用联合检测结束是否安全?

iBu*_*Bug 10 c endianness unions language-lawyer

换句话说,根据C 标准,这段代码安全吗?(假设uint8_t是一个字节)

void detectEndianness(void){
    union {
        uint16_t w;
        uint8_t b;
    } a;
    a.w = 0x00FFU;
    if (a.b == 0xFFU) {
        puts("Little endian.");
    }
    else if (a.b == 0U) {
        puts("Big endian.");
    }
    else {
        puts("Stack Overflow endian.");
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我把它改成这个怎么办?请注意if我所知道的第三种情况.

a.w = 1U;
if (a.b == 1U) { puts("Little endian."); }
else if (a.b == 0U) { puts ("Big endian."); }
else if (a.b == 0x80U) { /* Special potential */ }
else { puts("Stack Overflow endian."); }
Run Code Online (Sandbox Code Playgroud)

Sto*_*ica 6

引自n1570:

6.5.2.3结构和工会成员 - 第3页

后缀表达式后跟.运算符和标识符指定结构或联合对象的成员.该值是指定成员的值,如果第一个表达式是左值,则该值是左值.

6.2.6类型的表示/ 1概述 - 第7页

当值存储在union类型的对象的成员中时,对象表示的字节与该成员不对应但与其他成员对应的字节采用未指定的值.

这是允许的.如果考虑到注释95(尽管只提供信息),您的用例甚至可以被视为一个预期目的:

如果用于读取union对象的内容的成员与上次用于在对象中存储值的成员不同,则将值的对象表示的适当部分重新解释为新类型中的对象表示形式在6.2.6中描述(一个过程有时称为"类型双关语").这可能是陷阱表示.

现在,因为uintN_t系列类型被定义为没有填充位

7.20.1.1精确宽度整数类型 - p2

typedef名称uintN_t指定一个宽度为N且没有填充位的无符号整数类型.因此,uint24_t表示这样的无符号整数类型,其宽度恰好为24位.

它们的所有位表示都是有效值,没有陷阱表示是可能的.所以我们必须得出结论,它确实会检查结果uint16_t.

  • `uintN_t`类型定义为*"UINTN_MAX正好为2 ^ N - 1"*且没有填充位.应该没有陷阱表示. (2认同)