c++ - 这个 DWORD 相关代码是未定义行为吗?

标签 c++ undefined-behavior

这是我第三次尝试澄清我对这个话题的困惑。但这次我有不同的问题。

我有这个代码

  DWORD v1, v2, v3, Build;
  GetVersion(&v1, &v2, &v3, &Build);
  sprintf(VersionStr, "%d.%d.%d.%d", v1, v2, v3, Build);

大概是 10 年前使用 Visual Studio 编写的。我知道 DWORD 始终是 unsigned - 这是真的吗?

现在,here ,其中一个答案引用了某个版本的标准(这个标准版本是否适用于我的代码?),其中说明了 va_arg:

The standard isn't 100% clear on this point. On one hand, you get the specification for va_arg, which says (§7.15.1.1/2):

If there is no actual next argument, or if type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined, except for the following cases:

one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types;

one type is pointer to void and the other is a pointer to a character type.

另一方面,这个答案也提到了 printf

On the other hand, you get the specification of printf (§7.19.6.1/9):

If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined."

所以他首先引用了关于 va_arg 的引用,然后引用了关于 printf 的引用。看来他也不清楚。另一个答案提到尽管有 va_arg 文档,但无论如何这都违反了 printf 契约(Contract)。请看线程。我很困惑。


所以我的问题基本上是我在任何情况下都呈现未定义行为的代码?或者例如 v1 的值可以用 int 表示,这不是未定义的行为(正如我引用的其中一个答案中所声称的那样) )?

也可能是因为我的代码很旧,可能是因为旧版本的标准不是未定义的行为?

最佳答案

这真的很简单:sprintf 中的格式说明符必须 与传递的参数类型相匹配。请不要试图推测此规则的异常(exception)情况。

由于 DWORD 是 unsigned long%d 不是 unsigned long 的正确格式说明符>,您的程序的行为未定义。您必须使用%lu。由于 DWORD 不是标准类型,您应该包含一行

static_assert(std::is_same<DWORD, unsigned long>::value, "DWORD is not an unsigned long");

在你程序的某处。

关于c++ - 这个 DWORD 相关代码是未定义行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33673798/

相关文章:

c - 当 p 指向一个字符时,strcmp(p, "\n") 是未定义的行为吗?

c++ - noexcept 依赖于成员函数的 noexcept

c++ - 如何对模板类内的嵌套类使用作用域解析运算符?

c++ - 将带有 automake 的预构建二进制文件放在哪里?

c++ - 如何使用自定义分配器(没有 UB)提供的指向原始内存的指针?

c++ - 将对象实例作为函数参数传递——此代码是否调用未定义的行为?

c - 不同类型和大小的指针的 union

C++ 多态静态可变子函数指针

c++ - 继承层次结构中的析构函数顺序

c - 在内联 x86 程序集中是否未定义整数溢出?