【问题标题】:Is accessing int as unsigned long undefined behavior?是否将 int 作为 unsigned long 未定义行为访问?
【发布时间】:2020-04-01 22:13:29
【问题描述】:

在一本名为 Programming Windows 的书中,在其中一个示例中,我们有 this 行:

ReadFile (hFile, buffer, MAXREAD, &i, NULL) ;

i 这里是previously 声明为int,但ReadFile 的第四个参数是LPDWORD,这是DWORD* 的typedef,DWORDunsigned long 的typedef .它实际上是类型双关语。在大多数系统上,unsigned longint 的大小相同,但我认为像访问其他类型一样访问变量是未定义的行为。这样好吗?仅当尺寸相同时才可以吗?这是UB吗?我检查了几个勘误表网站,他们似乎没有列出这个。我错过了什么吗?

【问题讨论】:

  • 在大多数系统上,unsigned longint 大小相同 不,它们不是。 Windows 是这里的异常值。在几乎所有其他 64 位架构上,int 是 32 位,而 [unsigned] long 是 64 位。
  • 这是书中的错误。 i 应声明为 DWORD
  • 如果读到2GB(第31位为零),没有问题。
  • 请注意,最近 VC++ 会对此发出警告。这不是最佳做法。

标签: c winapi type-punning


【解决方案1】:

如果 DWORD 如您所描述的那样定义,则代码包含编译器必须诊断的约束冲突,并且标准不再涵盖生成的任何可执行文件的行为。 There is no implicit conversionint *unsigned long *,不管类型的大小。

如果您没有看到编译器错误消息,我强烈建议您调整编译器设置,以便显示错误消息。一些编译器默认为这个错误显示“警告”消息,这可能会误导粗心的人认为没有真正的问题。

【讨论】:

  • 在 C++ 中,指针类型之间没有隐式转换,但我认为在 C 中有。你能引用标准的相关部分说这是未定义的吗?有些人声称如果它们的大小相同就可以,其他人则声称如果您阅读的内容不超过int 可以容纳的内容,那就可以了。
  • @Ayxan 我添加了关于该主题的另一个 l-l 问题的链接,该人引用了问题中的标准
  • @Ayxan 程序无效(在 C 或 C++ 中)所以这里没有定义。
  • “编译器必须诊断” - 你能提供参考吗?我相信这是一个可怕的 IFNDR 的例子(病态,不需要诊断)。
  • @IInspectable C 没有“格式错误”,您正在考虑另一种语言。在我对相关标准引用的回答中有一个链接表明它是违反约束的,另请参阅 C11 5.1.1.3 指定违反约束必须产生诊断
猜你喜欢
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-20
  • 1970-01-01
  • 2016-06-28
  • 1970-01-01
相关资源
最近更新 更多