【问题标题】:Why printf(char[]) generates a warning, meanwhile printf("asdf") doesn't [duplicate]为什么 printf(char[]) 会生成警告,同时 printf("asdf") 不会[重复]
【发布时间】:2012-07-10 15:04:55
【问题描述】:

可能重复:
warning: format not a string literal and no format arguments

我有一个非常简单的问题:为什么当我制作 char[] s = "hi"; printf(s) 时它会发出警告:“警告:格式不是字符串文字并且没有格式参数”,而 printf("aa") 不会。

我已经读过 char 数组和字符串字面量之间的区别(一个是 const char const*,另一个是 char*),但来自 printf() 签名:

http://www.gnu.org/software/libc/manual/html_node/Formatted-Output-Functions.html#Formatted-Output-Functions

我发现它适用于任何类型。所以我的问题是为什么printf("aaa") 不发出任何警告(它是否以某种方式检查文字是常量,而数组不是)?

【问题讨论】:

  • FWIW,VC++ 不会抱怨非常量文字。
  • 哪个编译器对您的代码执行此操作?
  • @Mystical,我同意。 VC没有抱怨。想知道为什么其他编译器兼容或为什么 VC 不兼容?
  • @Jay gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

标签: c gcc printf


【解决方案1】:

如今,GNU 编译器和许多其他编译器确实会根据提供的参数检查printf-family 的格式字符串。编译器警告它不能对非文字字符串执行此操作。

使用非文字格式字符串被认为是一种不好的做法。使用您无法控制的格式字符串更糟糕。

【讨论】:

  • 如果我理解正确,您的意思是因为字符串文字被复制到一个数组中,编译器在编译时不知道该数组包含什么,因此它无法检查它是否内容是一个很好的格式字符串以及提供的参数。
  • 但是为什么const char* s = "hi"; printf(s) 也会产生警告呢?
  • 哦,我发现const char const* s = "hi"; printf(s) 不会产生任何错误。所以const char const* 似乎是字符串文字的类型。
  • 因为有人可以为s分配不同的指针。
  • @Jens,ty。是的,我后来意识到了。
【解决方案2】:

原因是大约 10 到 15 年前,由于人们假设在“s”有用户提供的输入时调用 printf(s) 是安全的,从而导致了一系列安全问题。许多编译器为此添加了警告以避免这些问题。如果您只想打印出一个字符串,请改用 puts()。如果您不确定您发送到 printf 的字符串不包含 '%' 字符,则应使用 printf("%s", s);

【讨论】:

    【解决方案3】:

    我敢打赌,在第二种情况下,编译器会看到字符串中没有格式,因此并不危险:

    /* "aa" is not dangerous, so do not display a warning */
    printf("aa")
    

    第一种情况,编译器可能看不到格式字符串的值,所以无法验证:

    /* the compiler doesn't know the content of the memory region pointed by `s`, so
       he can't determine if it's dangerous or not. Then display a warning */
    printf(s)
    

    【讨论】:

      【解决方案4】:

      免责声明:我不知道这是否是警告的原因,但这是一个原因。

      由于prinrf 的参数数量取决于转换说明符的数量,因此不 使用字符串文字作为格式字符串是非常罕见的(即,可能是错误)。此外,如果格式字符串不是文字,它确实来自其他地方——例如用户或文件输入。在这种情况下,错误(或恶意)输入可能会使您的程序崩溃,或者更糟的是,注入代码(即安全漏洞)。

      在任何情况下,如果你想打印一些不是文字的东西,并且没有格式参数,你很可能会寻找puts,而不是printf。 (恕我直言,puts 是 C 库中使用最少的函数。您曾经见过使用它的“hello, world”吗?)

      【讨论】:

      • 我读过一些关于puts的文章。
      猜你喜欢
      • 2012-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-03
      相关资源
      最近更新 更多