【发布时间】:2015-11-12 14:30:29
【问题描述】:
这是我第三次尝试澄清我对这个话题的困惑。但这次我有不同的问题。
我有这个代码
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:
在这一点上,标准并不是 100% 明确的。一方面,你得到 va_arg 的规范,其中 (§7.15.1.1/2):
如果没有实际的下一个参数,或者类型不兼容 实际下一个参数的类型(根据 默认参数提升),行为未定义,除了 以下情况:
一种类型是有符号整数类型,另一种类型是 对应的无符号整数类型,,其值可以表示为 两种类型;
一种是指向void的指针,另一种是指向字符的指针 输入。
另一方面,这个答案也提到了printf
另一方面,您会得到 printf 的规范(第 7.19.6.1/9 节):
如果任何参数不是对应的正确类型 转换规范,行为未定义。”
所以他首先引用了关于va_arg 的引用,然后引用了关于printf 的引用。他似乎也不清楚。另一个答案提到这违反了printf 合同,尽管有va_arg 文档。请看线程。我很困惑。
所以我的问题基本上是我在任何情况下都呈现未定义行为的代码?或者例如对于可以用int 表示的v1 的值,这不是未定义的行为(如我引用的答案之一所述)?
也可能是因为我的代码很旧,可能是旧版本的标准不是未定义的行为?
【问题讨论】:
-
提出这个问题没有错。加一。但是,您的程序的行为是未定义的,这是无法回避的事实。
-
@Bathsheba:我明白了,但我也发布了指向其他似乎声称这是安全的答案的链接
-
仔细阅读该标准会发现它并不安全。你真的应该在你的开发流程中安排一个修复。
-
@Bathsheba:另外,标准是否适用于我的代码,我的意思是如果我的代码是旧的,并且可能最近在标准中引入了 UB?
-
遗憾的是:即使在我的 C 大学时代(1990 年代),不匹配的 printf 参数也是未定义的。