【问题标题】:How do the printf function in C get the size of every parameter in the variable parameters list?C中的printf函数如何获取可变参数列表中每个参数的大小?
【发布时间】:2017-07-06 20:49:26
【问题描述】:

最近,我尝试了解 printf 在 C 中的详细实现, 我已经了解 va_start、va_arg 和 va_end 的用法, 但我总是无法理解的一个问题是 printf 如何获取参数列表中每个参数的大小,尽管它知道输出格式(%d、%c 等)。举一个例子更直观地展示我的问题:

int a = 27;
char b = 19;
printf("%d, %c", a, b);

我知道的 printf 的详细实现是: 第一步:通过宏 va_start(args, format) 获取指向变量参数开始的指针,format 是指向下面字符串 "%d, %c" 的 char 指针,args 是指向变量参数开始的指针位于堆栈中; 第二步:通过宏va_arg(args, int)获取每个参数的值,然后根据格式字符串输出参数; 第三步:使用va_end(args),清除args指针;

我无法理解的关键点是,当函数要输出a的值时,为什么它可以知道使用“int”作为宏va_arg的第二个参数?宏va_arg的具体实现是根据args指向栈的指针来获取数据,获取数据的长度取决于第二个参数,这里是int,为什么要给va_arg注入“int”而不是“char”或者“long int”,什么条件让它知道注入“int”? 条件是格式字符串? 在上面的例子中,它不能得到a的大小,只依赖于“%d”。

非常感谢您提前解释。

【问题讨论】:

  • 你知道 C 的默认参数提升的概念吗?我认为,这是拼图中缺失的部分。关键是很难将char 传递给代码中显示的函数。

标签: c logging printf


【解决方案1】:

...输出a的值,为什么知道用int作为宏va_arg的第二个参数?

因为你是这么说的。

%d 转换需要int 作为输入,因此printf 假定您传递了正确的类型。

如果您弄错了(即,您为 %d 转换说明符传递了一个字符),它将中断,这是您的错。

我本地手册页中的相关文字是:

参数必须与转换说明符正确对应(在类型提升之后)。

this reference 有一个详细的表格,描述了每个转换说明符所需的参数类型。如果您的参数类型与格式字符串不匹配,一些编译器或静态分析器会警告您,但正确编码始终是您的最终责任。

【讨论】:

  • 非常感谢,有你的回答,我现在可以理解了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-08
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多