首页 文章

WinAPI将POD与基本类型联合起来:依赖于实现还是符合标准?

提问于
浏览
1

在处理Windows API时,当需要大量数据时,经常会遇到结构 . MSDN文档鼓励在这些结构上使用union punning将它们转换为基本类型 . 这些转换是否符合标准,或MSDN是否建议可能导致未定义行为的技术?

例如,当处理FILETIME结构并且需要完成算术时,the MSDN documentation建议:

建议您不要在FILETIME结构中添加和减去值以获得相对时间 . 相反,您应该将文件时间的低位和高位部分复制到ULARGE_INTEGER结构,对QuadPart成员执行64位算术运算,并将LowPart和HighPart成员复制到FILETIME结构中 .

声明了ULARGE_INTEGER

typedef union _ULARGE_INTEGER {
  struct {
    DWORD LowPart;
    DWORD HighPart;
  };
  struct {
    DWORD LowPart;
    DWORD HighPart;
  } u;
  ULONGLONG QuadPart;
} ULARGE_INTEGER, *PULARGE_INTEGER;

那么文档建议的是什么,例如计算时间 Span ,是这样的:

FILETIME filetime[2];
ULARGE_INTEGER large[2];
// ...
large[0].LowPart  = filetime[0].dwLowDateTime;
large[0].HighPart = filetime[0].dwHighDateTime;
large[1].LowPart  = filetime[1].dwLowDateTime;
large[1].HighPart = filetime[1].dwHighDateTime;

auto diff = large[1].QuadPart - large[0].QuadPart;

该标准有一个臭名昭着的部分,总是提出类似的问题(引用N3337):

在联合中,最多一个非静态数据成员可以在任何时间处于活动状态,也就是说,任何时候最多一个非静态数据成员的值都可以存储在并集中 . [注意:为了简化联合的使用,我们做了一个特别的保证:如果标准布局联合包含几个共享公共初始序列(9.2)的标准布局结构,并且这个标准布局联合类型的对象包含一个标准布局结构,允许检查任何标准布局结构成员的公共初始序列;见9.2 . - 结束说明]

9.2具体是指结构 .

由于ULONGLONG解析为__int64或double,因此ULARGE_INTEGER联合包含两个结构和一个基本类型 . 在我阅读它时,引用的特殊保证不适用,因为设置HighPart和LowPart以及后续读取QuadPart将设置结构的两个成员然后读取基本类型 . 引用要求所有包含的实体可以互换地读/写为 structs .

那么MSDN建议在这种特殊情况下违反标准的技术还是我弄错了?

1 回答

  • 2

    严格遵循C标准,行为确实是未定义的(正如您的推理) . 但是,请记住,标准没有定义,仍然可以通过实现来定义 . 如果MSDN是用MSVC编译器编写的,那么我就不会感到惊讶,在这种情况下可以很好地提供定义的行为 . 我相信GCC也会声明基于联合的类型惩罚 .

相关问题