【问题标题】:Why does gcc -Wall give warning about zero-length format string?为什么 gcc -Wall 会发出有关零长度格式字符串的警告?
【发布时间】:2012-03-29 13:47:07
【问题描述】:

我搜索了一些有关这方面的信息,但没有找到任何令人满意的信息。函数调用是否有一些特殊行为

sprintf(someString, "");

这解释了为什么这是警告(在带有 -Wall 的 gcc 上)?我只是设法发现 C 标准允许零长度格式字符串。

我尝试了以下示例

#include <stdio.h>

int main()
{
    char str[2] = {'a', 'a'};
    sprintf(str, "");
    printf("\'%c\'\'%c\'\n", str[0], str[1]);
    return 0;
}

打印出来

'''a'

这正是我期望看到的。 那么,为什么会出现警告?

【问题讨论】:

  • sprintf(str, "%s", ""); 不会让编译器哭泣。

标签: c gcc string-formatting printf gcc-warning


【解决方案1】:

GCC 发出警告的事实通常与构造是否合法 C 无关,而是 GCC 开发人员是否认为这可能表明您的意思可能不是您编写的内容,或者只是风格不佳。以下是一些示例:

  • if (x = 0) — 你几乎肯定是指 if (x == 0)
  • printf(str) — 你几乎肯定是指fputs(str, stdout)printf("%s", str);正如所写,代码非常危险。
  • if (foo == bar &amp; MASK) — 你几乎肯定是指 if (foo == (bar &amp; MASK))

等等

在您的情况下,我认为 GCC 质疑您为什么调用 sprintf(String, "") 来执行与 String[0]=0; 等效的操作(后者更短、更快、更清晰)。

【讨论】:

  • 我同意这会更好,我只是不知道是否还有更多理由将其视为警告。我当然没有权威,但我不认为这种对合理编程的特殊冒犯会被认为值得警告
  • 我同意,但是 GCC 通过警告做了很多烦人的事情。这绝对是一个较轻的罪行。更大的一个是对未使用的函数参数发出警告,当您使用必须符合特定签名的函数指针时,这是不可避免的
  • @R 只是不命名函数参数,一切都很好:int op(int a, int) { return -a; }:未使用的第二个参数没有警告。
  • 如果他们担心效率,他们可以只生成String[0]=0; 而不是报告可疑警告。而且我认为sprintf(String, "") 更清楚,因为它比String[0]=0; 更好地表达了“使字符串为空”的想法,这意味着“使字符串的第一个字节为零”。
  • 虽然警告对文字 printfsprintf 调用很有用,但不幸的是,同样的警告适用于任何使用“看起来像 printf”属性的用户定义函数。此类用户定义的函数可以具有其他效果(例如打印前缀或终止),即使在字符串为空时也很有用。
【解决方案2】:

您收到警告是因为 gcc 知道 sprintf() 的第二个参数应该是一个非空字符串,通常是一个具有各种格式规范的字符串 - 对您所使用的字符串的功能等效且“更合法”的调用在你的代码中做的是sprintf(str, "%s", "")。此外,几乎总是有 1 到 N 个附加参数,足以满足格式规范。当您在这里使用它时,您将它用作strcpy() 的一种,虽然在技术上是有效的,但它是使用标准库的一种非常奇怪的方式。

【讨论】:

    【解决方案3】:

    这只是 GCC 的警告。如果您希望在您的应用程序的一部分中抑制它,您可以执行以下操作:

    #pragma GCC diagnostic ignored "-Wformat-zero-length"
    int main()
    {
         // code that produces a warning
    }
    #pragma GCC diagnostic warning "-Wformat-zero-length"
    

    【讨论】:

    • 我知道我可以摆脱它,我想知道为什么它一开始就在那里
    • 我认为这只是一个无意义的、有害的警告。根据预处理器宏的定义/值,它肯定会咬住格式字符串为零长度或非平凡的代码,并且这样的代码似乎非常合理。
    • 没有有害。它只是让您知道您的代码存在问题,您可能犯了错误。尽管sprintf (str, ""); 是合法的,但它是使 str 长度为零的字符串的一种相当迂回的方法,并且可能表明代码中存在逻辑错误。这不是被禁止的;刚刚引起您的注意。
    • @Phil,这是有害的,因为误报使识别真正的正警告更加困难。 -Wall 的大部分/全部都是您想要修复的合法内容,所以这很伤人。
    • 这个警告使得很难调用暴露的__attribute__((format(printf(...)))) 库设置器函数来将未暴露的字符串缓冲区设置为-Werror 代码中的空字符串(例如User_details_set(&amp;user, "");
    猜你喜欢
    • 2018-07-18
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-05
    相关资源
    最近更新 更多