This question already has answers here:
will casting around sockaddr_storage and sockaddr_in break strict aliasing

(2个答案)


3年前关闭。




在有关某个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];
};

最佳答案

在C诞生之初(至少可以追溯到1974年)和1989年之间,如果两个结构共享一个Common Initial Sequence,则该语言明确地允许代码使用一种结构类型的指针来检查另一种结构的CIS成员。在C99标准中,该权限仅限于两种结构类型都是联合体类型的一部分的情况,这种联合体类型的完整声明在检查CIS值时可见;有人坚持认为,由于1989年的作者打算施加这样的限制,因此它也适用于C89。另外,一些编译器作者坚持认为,由于该标准的作者仅是希望将该保证应用于通过并集类型的左值进行的访问,因此他们将忽略该标准中有关“完整并集类型”的定义的部分。 ”必须可见。

允许实现提供超出标准要求的保证。因为在C99之前编写代码的非心理人士没有理由期望他们需要包括不必要的工会声明才能利用CIS保证,并且从那个时代开始编写的许多代码都依赖于那些保证,尽管缺少此类声明,无论标准是否要求此类支持,任何想编写适合于此类代码使用的实现的人都必须支持它们。尽管没有特别好的理由说明对头文件的更新中不应包含联合类型声明,但我不确定有多少编译器会关心它的存在与否。我见过的编译器即使没有可见完整的联合类型声明也支持CIS保证,或者即使存在声明也拒绝CIS保证(忽略标准)。

关于c++ - C++严格的别名:这不是MSFT示例UB吗? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44816024/

10-09 00:21