The width and precision formatting parameters may be omitted, or they can be a fixed number embedded in the format string, or passed as another function argument when indicated by an asterisk "*
" in the format string. For example printf("%*d", 5, 10)
will result in " 10
" being printed, with a total width of 5 characters, and printf("%.*s", 3, "abcdef")
will result in "abc
" being printed.
----------------------------------以上内容是11月21日更新,来自wikipedia------------------------------------------------------------
今天遇到一个从来没有遇到过的很神奇的表达式——
printf("%*d",5,10);
printf("%d",10);这谁都知道,打印整形数据10,完事,但是。。。但是如果%后面跟了个*捏?而且有对应的参数是个神马情况捏?
事实是这里的*对应的参数,也就是例子里面的5,控制数字前输出的空格!
神奇吧,自己试试printf("%*d",5,10);这个语句
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面请允许我自恋的扮演一下福尔摩斯,找出真相。。。
首先找到,printf的实现代码,GCC里面printf是个壳,也就是说他是利用别人的功能实现的,而这里的”别人“其实就是真正实现数据输出的是下面这个东西
。。。。
_doprnt (const char *format, va_list ap, FILE *stream) { const char * ptr = format; char specifier[128];//格式化输出的那个常量字符串的缓冲区,很关键的一个东东 int total_printed = 0; while (*ptr != '\0') { if (*ptr != '%') /* While we have regular characters, print them. */ PRINT_CHAR(*ptr); else /* We got a format specifier! */当”扫描"到%的时候,就说明要发生格式化输出了,并且%之后的那个格式说明符就是该数据的读取格式 { char * sptr = specifier;//指针sptr指向那个缓冲区 int wide_width = 0, short_width = 0; *sptr++ = *ptr++; /* Copy the % and move forward. */把%保存到格式化输出的那个缓冲区 while (strchr ("-+ #0", *ptr)) /* Move past flags. */读者可以无视这个,和本主题无关 *sptr++ = *ptr++; if (*ptr == '*')关键的到了!如果那个printf里面那个常量字符串里%后面跟了个*就执行 COPY_VA_INT;这里是个宏定义,我们来看看宏定义是什么 COPY_VA_INT;
#define COPY_VA_INT
do { \ const int value = abs (va_arg (ap, int)); \ 取变长参数列表里那个对应的那个参数,此处是5,然后赋值给变量value char buf[32]; \ 一个新的缓冲区 ptr++; /* Go past the asterisk. */ \ 指向printf常量字符串的下一个位置,这个和主题关系不大,和谐掉 *sptr = '\0'; /* NULL terminate sptr. */ \ 把指向specifier 缓冲区当前位置的指针指向一个空字符 sprintf(buf, "%d", value); \把value的值写到buf缓冲区里面 strcat(sptr, buf); \把buf缓冲区的内容“衔接”到sptr的后面!事情就发生变化了,格式化输出的格式说明符%之后就变成 %5d!!!!所以会有空格输出 while (*sptr) sptr++; \ } while (0)