%*.*d 在 printf() 中是如何工作的

How does %*.*d work in printf()?

本文关键字:何工作 工作 printf      更新时间:2023-10-16
#include <stdio.h>
int main()
{
  printf("%*.*dn", -6 , 7,20000);
  printf("%*.*dn", 5, -6, 2000);
  return 0;
}

输出:

0020000
 2000

我不明白printf如何解释格式说明符 * . *

在第一次调用 printf() 时,后面的 7 会覆盖前 -6 吗?所以输出宽度的大小变成7?

.之前*的参数是字段宽度.*的参数是精度

字段宽度是转换后将输出的最小字节数;如果生成的字节较少,则输出将被填充(默认情况下,左侧带有空格,但左零填充和右侧空格填充也是选项,由标志控制(。宽度*的负参数被解释为带有 - 标志的相应正值,这会将填充向右移动(即左对齐字段(。

另一方面,精度的含义根据正在执行的转换而变化。负精度被视为根本没有指定精度。对于整数,它是要生成的最小位数(而不是总输出(;如果生成的数字较少,则在左侧添加零。显式精度为 0 会导致在值为 0 时不生成任何数字(而不是生成单个0(。对于字符串,精度会限制输出字节数,必要时截断字符串(并允许更长的非以 null 结尾的输入数组(。对于浮点说明符,精度控制在基数点之后打印的位置数(对于 %f (或总重要位置(对于其他格式(。

在您的示例中:

printf("%*.*dn", -6 , 7,20000);

此处的字段是左对齐的(右侧填充(,最小宽度为 6,但该字段最终会变宽,因此宽度将被忽略。精度 7 强制整数输出至少为 7 位,因此您最终会得到 0020000 作为转换后的字段内容,这已经超出了宽度。

在另一个中:

printf("%*.*dn", 5, -6, 2000);

字段宽度为 5,默认右对齐;填充在左侧带有空格。负精度将被忽略,就好像没有指定一样,因此转换后的字段内容2000,只有 4 个字节,最多填充 5 个字节,以通过单个前导空格填充宽度。

printf("%*.*dn", -6 , 7,20000); 

printf("%-6.7dn, 20000);

这只是为动态格式提供了一种方式。

这是 glibc 中 printf 的源代码

/* VARARGS1 */
int  __printf (const char *format, ...)
{
 va_list arg;
 int done;
 va_start (arg, format);
 done = vfprintf (stdout, format, arg);
 va_end (arg);
 return done;

}

如您所见,printf 从va_list获取参数

这是另一个示例,向您展示 printf 的工作原理:

/* va_start example */
#include <stdio.h>      /* printf */
#include <stdarg.h>     /* va_list, va_start, va_arg, va_end */
void PrintFloats (int n, ...)
{
  int i;
  double val;
  printf ("Printing floats:");
  va_list vl;
  va_start(vl,n);
  for (i=0;i<n;i++)
  {
    val=va_arg(vl,double);
    printf (" [%.2f]",val);
  }
  va_end(vl);
  printf ("n");
}
int main ()
{
  PrintFloats (3,3.14159,2.71828,1.41421);
  return 0;
}