Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C printf/sprintf编译器警告是概念上的突破吗?_C_Compiler Construction_Warnings_Printf - Fatal编程技术网

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

C printf/sprintf编译器警告是概念上的突破吗?,c,compiler-construction,warnings,printf,C,Compiler Construction,Warnings,Printf,我注意到,当printf/sprintf函数的格式字符串中的转换说明符与相应参数的类型或计数不匹配时,大量C编译器会发出警告 在我看来,这似乎是一个概念上的突破,因为根据语言规范,C没有内置函数 编译器应该知道的关于printf/sprintf的一切是它们的原型,而不是它们的语义。我知道printf/sprintf是标准的C函数,但它们驻留在一个单独的库libc中,您必须包含stdio.h才能导入它们的原型 许多编译器所做的是分析格式字符串,这也可以在运行时提供 上述警告有意义吗?这些警告表明可

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

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


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

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


上述警告有意义吗?

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

是的,在编译器中为警告设置特殊情况可能看起来不一致(假设
不只是具有
\uu printf\u warning
属性或类似属性),但是,如果它有用并且有助于解决一些错误(甚至可能是安全错误),那么为什么不设置它们呢

我的意思是,并不是每个人都只是用自己的libc替换它们自己的libc,使用不同的printf语义…

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

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

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

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


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

如果我正确理解了你的问题,我同意您的假设,即编译器对
printf
和朋友的格式字符串的验证在概念上不同于编译器执行的其他类型的静态检查(语法、类型等)


然而,它是标准允许的,并且对我们这些可怜的程序员有很大的帮助。

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

在许多情况下,实现可能会生成警告,但没有一种情况是正确的 作为本国际标准的一部分规定

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


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

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


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

编程语言标准的最终目的是帮助程序员编写按预期运行的程序。标准中没有规定编译器在遇到“bigvar=byte3”时应该发出警告,这是一个与什么概念不同的词:QOI(事实上是3)@马丁:据我所知,C没有内置函数。那么,当printf/sprintf函数在外部库中定义时,编译器如何理解它们的语义?@Blagovest:语义不是在任何库中定义的,而是在标准中定义的(主要是:实现可以添加新的格式说明符)。您的实现可能会使用一些链接的共享对象来提供实际的代码,但这并不会改变函数的定义行为。@Blagovest Buyukliev:大多数情况下,这些操作都是由函数声明中特定于编译器的属性强制执行的(例如,
\uu属性(gcc中的格式(printf,m,n))
)也就是说,函数是否具有类似于printf的语义。“该标准在某些情况下需要诊断”——不需要,请参见我回答中的引文(来自ISO/IEC 9899:TC2)。或者你能给我指出一个地方(可能是在其他ISO或ANSI C标准中)它有这样的语义吗?我这里有C99标准草案(不拥有真实副本),在5.1.1.3中,我发现“一致性实施应产生至少一条诊断信息(以实施定义的方式识别)如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的行为,即使该行为也被明确指定为未定义或实现已定义。“最终版本中是否省略了此内容?@Roman:另外,i