在调用遗留C API(如getnameinfo
)时,现代C ++中正确的方法是将指针到结构的参数正确地转换为指向另一个结构的指针,这种结构具有相似的布局,但是哪个与原始结构的类层次结构无关?
例如,getnameinfo
接受第一个参数a const struct sockaddr *
,但在处理const struct sockaddr_storage *
时也应该有效。但是,AFAIK只是reinterpret_cast
指针被C ++标准认为是UB。
在上面的示例中,给定一个sockaddr_storage
对象,将指针传递给getnameinfo
的正确方法是什么?
答案 0 :(得分:4)
我可能误读了标准,但由于这些类型是标准布局类型,如果您访问它们的公共初始子序列,它不是UB。我相信[class.mem/23]就是原因:
在具有struct类型T1的活动成员的标准布局并集中,允许读取结构类型T2的另一个union成员的非静态数据成员m,前提是m是T1的公共初始序列的一部分,并且T2;行为就像提名T1的相应成员一样。
这是对工会的明确许可,理论上可以通过编译魔术完成。但实际上我认为这意味着对于标准布局类,公共初始序列在内存中具有相同的布局。
现在让我们考虑[basic.lval/8.6]:
如果程序试图通过访问对象的存储值 行为是除以下类型之一以外的glvalue 未定义:
- ...
- 聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(包括, 递归地,子聚合的子元素或非静态数据成员 包含联盟),
- ...
当您取消引用重新解释的指针时,您将获得包含您访问的成员类型的聚合的glvalue。由于该成员属于共同的初始序列,所以一切都应该很好。
我怀疑这是一个理智的实现,这在图书馆边界不起作用。