繁体   English   中英

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

[英]Are printf/sprintf compiler warnings a conceptual break?

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

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

所有编译器都应该知道printf / sprintf是他们的原型而不是他们的语义。 我知道printf / sprintf是标准的C函数,但是它们存在于一个单独的库libc中,你必须包含stdio.h才能导入它们的原型。

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

以上是否有意义?

“所有编译器都应该知道printf / sprintf是他们的原型,而不是他们的语义”。

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

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

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

当然,如果格式说明符在运行时才知道,那么编译器就无法对varargs进行静态检查。 但是当它在编译时已知时,编译器可以假设printf的行为与它可以假设memcpy或整数加法的行为一样有效。

如果我正确地阅读了你的问题,我同意你的前提,即编译器对printf和朋友的格式字符串的验证是一种概念性的活动,与编译器完成的其他种类的静态检查(语法,类型等)不同。

但是,它是标准所允许的,并且可以帮助我们糟糕的程序员。

编译器的任务只是给你一些有用的提示。 标准不涵盖此行为。

实施可能会在许多情况下产生警告,其中没有一个被指定为本国际标准的一部分。

从理论上讲,没有什么能阻止编译器警告你(可能)错误地使用QT库。

printf是标准功能,因为它(包括其语义)被ISO C标准所涵盖。

标准在某些情况下需要诊断,但不禁止常规诊断。 任何实现都可以出于任何原因自由发布诊断,包括不正确使用printf()或过度使用字母Q.显然,其中一些原因比其他原因更有用。

此外,如果包含库,则其中的所有可见标识符都将保留。 您不能#include <stdio.h>并拥有自己的printf定义(参见C99标准草案的7.1.3)。 这意味着实现可以自由地假设您正在使用标准printf并将其视为标准的必需部分。

这些警告表明可能存在错误,因此非常有用。

是的,在编译器中有警告的特殊情况可能看起来不一致(假设<stdio.h>不仅具有__printf_format_warning属性或类似的东西),但是如果它有用并且有助于解决一些错误(也许甚至安全漏洞),为什么不拥有它们呢?

我的意思是,并不是每个人都只用自己的libc替换他们的libc,具有不同的printf语义......

编程语言标准的最终目的是帮助程序员编写符合预期的程序。 标准中没有任何内容表明如果遇到“bigvar = byte3 << 24 + byte2 << 16 + byte1 << 8 + byte0;”,编译器应该发出警告,但由于结果可能不是程序员打算,许多编译器会发出警告。 标准对警告施加的唯一限制是它们不能阻止合法程序的成功编译(例如,在输出999警告后输出错误的编译器,或者为了所有实际目的,输出如此多的警告编译将会,永远不会完成,不符合规定)。

没有任何要求编译器“知道”标准库,但也没有要求如果有人#includes正常的标题,它就不知道它们。 a program includes <stdio.h> I think it would be permissible under the standard for a compiler to replace a printf call that it can understand with something that might be easier to process at run-time (eg it could replace printf("Q%5d",foo); with "putch('Q'); __put_int(foo,5);" if desired). 实际上, 一个程序包含<stdio.h>我认为在编译器的标准下允许替换一个可以在运行时更容易处理的东西(例如它可以替换printf)的printf调用是允许的(“Q%5d”,foo);“putch('Q'); __put_int(foo,5);”如果需要,“。 如果程序没有#include <stdio.h>,则禁止此类翻译。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM