C fomat说明符的数量是否可以少于printf语句中的变量数量

C fomat说明符的数量是否可以少于printf语句中的变量数量,c,format,format-specifiers,C,Format,Format Specifiers,我在borland c编译器中编写了以下程序。我的疑问是为什么c编译器在编译时或运行时都不会抛出任何错误。该程序执行良好,输出为24 #include<stdio.h> #include<conio.h> int main(){ int a=2,b=4,c=6; printf("%d%d",a,b,c); getch(); return 0; } #包括 #包括 int main(){ INTA=2,b=4,c=6; printf(“%d%d”,a、b、c); getc

我在borland c编译器中编写了以下程序。我的疑问是为什么c编译器在编译时或运行时都不会抛出任何错误。该程序执行良好,输出为24

#include<stdio.h>
#include<conio.h>
int main(){
int a=2,b=4,c=6;
printf("%d%d",a,b,c);
getch();
return 0;
}
#包括
#包括
int main(){
INTA=2,b=4,c=6;
printf(“%d%d”,a、b、c);
getch();
返回0;
}
即使格式说明符的数量少于参数的数量,也不会抛出错误。这里发生了什么。


“这些参数的数量至少应与格式说明符中指定的值的数量相同。其他参数将被函数忽略。”

尽管您为
printf()
提供了三个变量,但只有两个格式说明符,因此,这两个变量将替换为前两个可用变量。

这将正常工作,但如果编译器设置为检查
printf
varargs参数,则可能会出现编译器错误

printf
函数是可变的,即采用可变数量的参数。格式字符串将指定使用的数量,如果指定的数量过多,则将忽略这些内容。POSIX参考是:其中说明:

如果在参数保留时格式已用尽,则应计算多余的参数,但在其他情况下忽略多余的参数

(基本的C参考是C 2011 7.21.6.1 2,来自-Thank@EricPostDischil-但这是一个701页的PDF)

然而,从变量函数的工作原理来看,这是相当明显的


相反的情况(变量少于格式说明符中的变量)是不允许的,因为
printf
函数将尝试访问堆栈上不存在的变量,从而产生未定义的行为。

因为您有一个接受变量数量的函数

intprintf(常量字符*格式,…)

在C语言中,这意味着没有参数类型检查,而且,
printf
不知道用户传递给函数的参数有多少。有一个技巧-
printf
计算
%
的数量并确定它是参数的数量。要了解其工作原理,您可以查看
va_列表
va_开始
va_结束
va_参数
。尝试运行printf(“%i,%i,%i”,a)-未定义的行为

fomat说明符的数量是否可以少于printf语句中的变量数量

答案是肯定的。根据C标准:

(c99,7.19.6.1p2)“如果在参数保持不变的情况下耗尽了格式,则会(一如既往地)计算多余的参数,但在其他情况下会忽略。”



它只是用前两个变量值替换了前两个格式说明符,从而建立了一个更好的编译器:。这就是为什么他们说启用编译器警告有帮助。我认为重要的是,
printf
只是一个普通函数,它(通常)不会得到编译器的特殊处理。在它的核心,编译器不必在格式说明符和参数之间建立任何关联—它所看到的只是一个字符串和一组参数,这些参数将在运行时进行计算—并且可能会很乐意接受类似于尝试使用
printf
a
float
%d
等。尽管现在有一些编译器和代码分析工具会警告您这一点。@user2802841“printf”接受带有“%d”的“float”值,但对于以下代码,输出是奇怪的浮点数a=5.0;printf(“%d”,a);输出是0,这是C++标准,而不是C标准。这是一个C问题。我意识到答案是一样的。@ AbLe: C++标准遵从C标准来定义C标准库函数。但是,提问者在C的假设下,假设不是C++,而不是C++,而不是C标准(或者是Posix标准)不是C++的正确答案(即使它遵从C标准)。我没有投票否决这个答案……Abbay:甚至不是C++标准。它是关于C++的第三方站点,注册到娟捜列。他为什么要运行调用未定义行为AMM的代码,以理解PrtTf(大多数变量函数)只关注格式ARG,Tayi不知道实际的参数计数。这是一种糟糕的方法吗?对我来说,这是一种糟糕的方法,因为从具有未定义行为的代码中得出的任何结论都是无效的-根据定义,未定义的行为意味着任何事情都可能发生。这回答了错误的问题。该问题询问的转换说明符少于格式字符串后的参数
printf(“%i”,a,a)
没有未定义的行为(假设
a
有合适的类型)。最新的C标准:7.16.1.1 va_arg宏:如果没有实际的下一个参数,或者如果类型与实际下一个参数的类型不兼容(根据默认参数升级升级),这种行为是不确定的,不是我,但可能是因为你回答了
printf(“%d%d”,a,b,c)的具体情况,OP想要一个通用的answer@FilipeGonçalves-也许你是对的,尽管我认为我的观点可以根据我提供的具体解释进行概括!除了7.21.6.1.2.这不是C参考之外,这与C 2011相同;它是一个POSIX(IEEE 1003.1)参考。它旨在与C保持一致,但对C没有权威性。C参考是C 2011 7.21.6.1 2。@EricPostpischil-足够公平。为了改进我的答案,是否有更好的(即HTML)直接引用C标准(相对于它的派生版本)。我已经被引用了,但是作为一个701页的PDF,它很难友好地指向人们。你可以引用任何来源“非正式地”回答问题,只要你不说它是C的“参考”。但是我发现C标准对于整个系统来说是相当可读的