【问题标题】:Why doesn't gcc -Wformat warn about printf %d on an unsigned int?为什么 gcc -Wformat 不警告 unsigned int 上的 printf %d?
【发布时间】:2012-07-03 11:08:26
【问题描述】:

以下程序具有未定义的行为:

#include <stdio.h>

int main(void)
{
    unsigned int x = -100; // This is fine, becomes UINT_MAX - 100
    printf("%d\n", x); // This is undefined behavior.
    return 0;
}

C99 7.19.6.1p8 声明 %d 需要一个 int 参数。

C99 7.19.6.1p9 声明“如果任何参数不是正确的类型 相应的转换规范,行为是 未定义。”

但是,gcc -Wformat(包含在-Wall 中)不会抱怨上述程序,为什么?这是一个错误,还是故意遗漏?

来自 gcc 手册页:

-Wformat

检查对"printf""scanf" 等的调用,以确保提供的参数具有适合指定格式字符串的类型,并且格式字符串中指定的转换有意义

【问题讨论】:

  • C99 6.3.1.3p3 说无符号到有符号的转换是实现定义的。
  • @user315052:没有转换; xunsigned int 对象)的表示形式被解释为类型为 int
  • @KeithThompson:我认为是因为 C99 7.15.1.1p2,最后一句,在通过 va_arg 宏转换参数类型时,它对有符号/无符号进行了例外处理。
  • @KeithThompson 代码中没有转换,只是因为函数是可变参数。如果函数被声明为采用int,则调用是合法的。那么为什么要期望 gcc 会针对法律案件发出警告呢?
  • @user315052:我刚读了那段;这并不意味着存在转换

标签: c gcc gcc-warning format-specifiers format-string


【解决方案1】:

我最好的猜测是警告被跳过了,因为 UB 可以说是由 value 而不仅仅是类型调用的。 va_arg 允许签名不匹配,只要值在有符号和无符号类型中都可以表示。但是,printf 和朋友们并没有按照va_arg 指定,并且标准规定任何类型不匹配都会导致 UB,但这可能是标准中的一个错误。否则,printf("%x",1); 将调用 UB。请参阅我关于该主题的问题:

Does printf("%x",1) invoke undefined behavior?

【讨论】:

  • 谢谢。这是有道理的,因为 6.2.5p6 要求 int 和 unsigned int 使用相同数量的存储空间。即使 unsigned 上的 printf %d 在技术上是未定义的,也没有合理的理由让它引起真正的问题。
  • 标准并没有说printf() 使用&lt;stdarg.h&gt;,但是你可以构造一个指向printf() 函数的指针可以通过它调用这一事实意味着至少在参数中有一些共性-传递机制。
  • GCC 5.0 现在有这样的警告:-Wformat-signedness(由-Wformat 启用)。
  • 在这里进行实验 rextester.com/live/CCQJKP79309 表明 -Wformat-signedness 有效,但未包含在 -Wformat 中
  • 作为一个单独选项的全部意义在于它没有。
猜你喜欢
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 2020-02-16
  • 1970-01-01
  • 2015-02-27
相关资源
最近更新 更多