最近,我尝试了解C中printf的详细实现, 我已经了解了va_start,va_arg和va_end的用法, 但是我总是无法理解的一个问题是printf如何获得参数列表中每个参数的大小,尽管它知道输出格式(%d,%c等)。举一个例子来更直观地展示我的问题:
int a = 27;
char b = 19;
printf("%d, %c", a, b);
我知道printf的详细工具是: 第1步:它通过使用宏va_start(args,format)获取指向变量参数开始的指针,格式是指向下面字符串“%d,%c”的char指针,args是指向可变参数的开始的指针位于堆栈中; 步骤2:使用宏va_arg(args,int)获取每个参数的值,然后根据格式字符串输出参数; 第3步:使用va_end(args),清除args指针;
我无法理解的关键点是当函数想要输出a的值时,为什么它可以知道使用“int”作为宏va_arg的第二个参数?宏va_arg的详细实现是根据指向堆栈的args指针获取数据,获取数据的长度取决于第二个参数,这里是int,为什么它将“int”注入va_arg而不是“char”或“long int”,什么条件让它知道注入“int”? 条件是格式字符串? 在上面的例子中,它不能得到a的大小,只取决于“%d”。
非常感谢您提前解释。
答案 0 :(得分:3)
...输出a的值,为什么它可以知道使用“int”作为宏va_arg的第二个参数?
因为你告诉了它。
%d
转化需要 int
作为输入,因此printf
假设您传递了正确的类型。
如果你弄错了(即你传递了一个%d
转换说明符的字符),它就会破坏,这是你的错。
我当地联机帮助页面的相关文字是:
参数必须与转换说明符正确对应(在类型提升后)。
this reference有一个详细的表,描述了每个转换说明符所需的参数类型。如果您的参数类型与您的格式字符串不匹配,某些编译器或静态分析器可能会发出警告,但最终您有责任正确编码。