代码之家  ›  专栏  ›  技术社区  ›  Blagovest Buyukliev

printf/sprintf编译器警告是概念上的突破吗?

  •  4
  • Blagovest Buyukliev  · 技术社区  · 15 年前

    我注意到,当printf/sprintf函数的格式字符串中的转换说明符与相应参数的类型或计数不匹配时,大量C编译器会发出警告。

    在我看来,这似乎是一个概念上的突破,因为根据语言规范,C没有内置函数。

    许多编译器所做的是分析格式字符串,也可以在运行时提供。

    上面说的有道理吗?

    6 回复  |  直到 15 年前
        1
  •  11
  •   Steve Jessop    15 年前

    “编译器应该了解printf/sprintf的是它们的原型,而不是它们的语义”。

    那是不正确的部分。就标准而言,C实现的任何部分都“被允许”了解任何其他部分,并发布可能对用户有帮助的诊断。编译器内部函数不是标准所要求的,这个特定的诊断也不是,但它们肯定不是禁止的。

    请注意(就标准而言)标准库是特殊的,它不仅仅是任何旧的链接库。如果一个特定的实现/编译器甚至为用户提供了一种机制来链接标准库的不同版本,那么当替代库的语义与标准中列出的不同时,标准肯定不要求它“工作”。

    因此在这个意义上,标准库中的所有内容都是“bult-ins”。它是C语言规范的一部分。编译器可以在假设其行为符合标准要求的前提下进行操作。

    当然,如果直到运行时才知道格式说明符,那么编译器就不能对varargs进行静态检查。但是当编译时知道它时,编译器可以假定 printf 就像它可以假设 memcpy ,或整数加法。

        2
  •  2
  •   Derrick Turk    15 年前

    如果我没看错你的问题,我同意你的假设 printf 编译器的friends格式字符串在概念上不同于编译器所做的其他类型的静态检查(语法、类型等)。

        3
  •  2
  •   Roman Cheplyaka    15 年前

    编译器的任务就是给你一些有用的提示。这种行为不在标准范围内。

    作为本国际标准的一部分。

    理论上,没有什么能阻止编译器警告您(可能)不正确地使用QT库。

    以及 printf 是ISO C标准涵盖的标准函数(包括其语义)。

        4
  •  2
  •   David Thornley    15 年前

    该标准要求在某些情况下进行诊断,但不允许进行一般诊断。任何实现都可以出于任何原因(包括不正确地使用 printf()

    此外,如果包含一个库,其中所有可见的标识符都将被保留。不允许你这样做 #include <stdio.h> 有你自己的定义 printf (见C99标准草案7.1.3)。这意味着实现可以自由地假设您正在使用标准 打印F 并将其视为标准的一部分。

        5
  •  1
  •   luiscubal    15 年前

    这些警告指示可能的错误,因此非常有用。

    <stdio.h> 不仅仅是有一个 __printf_format_warning 属性或类似的东西),但话说回来,如果它有用并且有助于解决一些bug(甚至可能是安全bug),那么为什么不让它们呢?

    我是说,并不是每个人都用自己的libc替换libc,用不同的printf语义。。。

        6
  •  1
  •   supercat    15 年前

    编程语言标准的最终目的是帮助程序员编写按预期运行的程序。标准中没有规定编译器在遇到“bigvar=byte3<<24+byte2<<16+byte1<<8+byte0;”时应发出警告,但由于结果可能不是程序员想要的,因此许多编译器都会发出警告。这些标准对警告的唯一限制是,它们不能阻止合法程序的成功编译(例如,一个编译器在输出999个警告后出现错误而失败,或者输出如此多的警告,以至于编译在所有实际用途中永远不会完成,这将是不一致的)。

    如果