C ++严格别名:这不是MSFT的例子UB吗?

时间:2017-06-29 03:45:36

标签: c++ winsock undefined-behavior strict-aliasing

在关于某个Winsock结构的this页面上,该示例似乎是获取结构的地址并将结果指针强制转换为指向完全不同的结构的指针。

SOCKET ListenSocket;
struct sockaddr_in saServer;
// Bind the listening socket using the information in the sockaddr structure
bind( ListenSocket,(SOCKADDR*) &saServer, sizeof(saServer) );

以下是两个结构的声明。这是技术上未定义的行为,对吗?

struct sockaddr {
        ushort  sa_family;
        char    sa_data[14];
};

struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};

1 个答案:

答案 0 :(得分:2)

在C的曙光(至少回到1974年)和1989年之间,如果两个结构共享一个公共初始序列,该语言明确地允许代码使用一种结构类型的指针来检查另一种结构类型的CIS成员。在C99标准中,该权限仅限于两种结构类型都是联合类型的一部分的情况,其中完整的声明在检查CIS值时可见;有些人坚持认为,因为1989年的作者意图施加这样的限制,它也适用于C89。此外,一些编译器编写者坚持认为,因为标准的作者只是为了保证适用于通过联合类型的左值进行的访问,他们会忽略标准的一部分,即&#的定义34;完整的联合类型"必须是可见的。

允许实施提供超出标准要求的保证。因为在C99之前编写代码的非心理人员没有理由期望他们需要包含其他不必要的联合声明以便利用CIS保证,并且因为从那个时代编写的大量代码依赖于这些保证,尽管缺少此类声明,任何想要编写适合与此类代码一起使用的实现的人都必须支持标准是否需要此类支持。虽然没有特别好的理由为什么头文件的更新不应该包含联合类型声明,但我不确定有多少编译器会关心它的存在与否。即使没有完整的联合类型声明,我所看到的编译器也支持CIS保证,或者即使声明存在,CIS也会保证(忽略标准)。