printf("%*d",5,10);这个表达式正确?如果正确输出什么?怎么实现的?

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)




------------------------------------------------------------------------------------------------------------------------------------

这里sptr是指向specifier缓冲区的,真正按格式化打印数据是按照specifier缓冲区里的字符串格式来打印的,所以如果你没看懂,可以简单的理解成*被替换成printf("%*d",number,var);中的number,然后按照printf("%number d"10);来格式化输出数据









  





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值