admin 管理员组

文章数量: 887031

[C语言]关于printf输出的奇怪事:printf(“%d %d %d %d %d\n“, ++i,

题目

打开这篇文章,屏幕前的你一定也是C语言大军中的一员,不知道你能否猜出下面几个程序的运行结果
1.

#include<stdio.h>
int main(){char s[]="123",*p;p=s;printf("%c%c%c\n",*p++,*p++,*p++);return 0;
}
#include<stdio.h>
int main(){char s[]="123",*p;p=s;printf("%c",*p++);printf("%c",*p++);printf("%c",*p++);return 0;
}
#include<stdio.h>
int main(){int a=0;printf("%d%d%d\n",a++,a++,a++);return 0;
}
#include<stdio.h>
int main(){int a=0;printf("%d",a++);printf("%d",a++);printf("%d",a++);return 0;
}
#include<stdio.h>
int main()
{int j = 8;printf("%d ", ++j);printf("%d ", --j);printf("%d ", j++);printf("%d ", --j);printf("%d\n", j);return 0;
}
#include<stdio.h>
int main()
{int i = 8;printf("%d %d %d %d %d\n", ++i, --i, i++,i--, i);return 0;
}

上面程序运行结果如下

  • 321
  • 123
  • 210
  • 012
  • 9 8 8 8 8
  • 8 8 7 8 8
    不知道屏幕前的你做对几道题呢?

如果全对了的话,那你
你可能对本片所讲的知识已经很熟悉了,可以选择不在看下去;
如果觉得文章有趣,想一探究竟,欢迎继续读下去

看到这里的同学可能作对了2、4和5,但是1、3和6有一些不太理解,为什么会这样呢?

解释

下面就为大家解惑,(2、4和5为正常情况,这里不在赘述)

首先,请大家观察一下1、3和6的共同点
最主要的是输出多个内容 %c%c%c 和%d%d%d

在输出这多个数据的时候,printf 的内部情况是怎么样的呢?

是从左到有依次进行输出吗? 从结果,我们可以发现,显然不是这种情况.

接下来,我们通过观察下面代码的反汇编,来逐步解释,是怎样执行的?
代码:

#include<stdio.h>
int main()
{int i = 8;printf("%d %d %d %d %d\n", ++i, --i, i++, i--, i);return 0;
}

汇编:

   int i = 8;
mov         dword ptr [i],8 printf("%d %d %d %d %d\n", ++i, --i, i++,i--, i);//i
mov         eax,dword ptr [i]//将i变量的值存放到eax寄存器中
//i--
mov         dword ptr [ebp-0DCh],eax //将eax寄存器中的值存放在一个临时变量中
mov         ecx,dword ptr [i] //将i变量的值存放到ecx寄存器中
sub         ecx,1 //ecx寄存器中的值-1
mov         dword ptr [i],ecx  //将ecx寄存器中的值写回i变量
//i++
mov         edx,dword ptr [i]//将i变量的值存放到edx寄存器中  
mov         dword ptr [ebp-0E0h],edx //将edx寄存器中的值存放在临时变量
mov         eax,dword ptr [i] //将i变量的值存放到eax寄存器中   
add         eax,1 //eax寄存器的值+1
mov         dword ptr [i],eax  //将eax寄存器中的值写回i变量
//--i
mov         ecx,dword ptr [i]  //将i变量的值存放到ecx寄存器中  
sub         ecx,1  //ecx寄存器的值+1
mov         dword ptr [i],ecx //   //将ecx寄存器中的值写回i变量
//++i
mov         edx,dword ptr [i] //将i变量的值存放到edx寄存器中   
add         edx,1  //edx寄存器的值+1
mov         dword ptr [i],edx   //将edx寄存器中的值写回i变量
//
mov         eax,dword ptr [i]  //将i变量的值存放到eax寄存器中 
push        eax  //将eax寄存器的值入栈
mov         ecx,dword ptr [ebp-0DCh] //将这个临时变量放到ecx寄存器  
push        ecx  //将ecx寄存器的值入栈
mov         edx,dword ptr [ebp-0E0h] //将这个临时变量放到edx寄存器
push        edx   //将edx寄存器的值入栈
mov         eax,dword ptr [i]  //将i变量的值存放到eax寄存器中
push        eax  //将eax寄存器的值入栈
mov         ecx,dword ptr [i]   //将i变量的值存放到ecx寄存器中
push        ecx //将ecx寄存器的值入栈

在上面汇编的解释中, 这个字,在最后出现多次。
可能有的小伙伴会很疑惑,什么是栈呢?

栈可以理解为一个容器,很想存放羽毛球的桶,我们先放入球桶当中的球一定是最后才能拿出来的,就像下面的过程,1我们最先放进去,最后取出来

通过之前的解释,大家也初步了解了 什么是栈?下面,我们就来演示一下代码的求取过程。

演示过程

首先,我们要明确,printf是一个stdio.h库中的一个函数,函数的参数是要存放在栈当中的。
即对于这一句 printf("%d %d %d %d %d\n", ++i, --i, i++, i--, i);
而言,可以使用下面进行表示

2.
我们从参数栈中取出表达式进行计算,计算结果也要放到一个栈(我们称其为结果栈)当中。
对于后置 ++ 或者 - - 而言,我们直接把结果放到结果栈中
对于前置 ++ 或者 - - 而言,我们把一个指向 i 变量的指针放入结果栈当中
对于一个变量而言,我们把一个指向 i 变量的指针放入结果栈当中

最终 i 的值为8;

我们使用 *(&i) 表示指向i变量的指针

从结果栈中取出结果,进行打印,上面的*(&i)表示最终 i 变量的值。

最终打印结果为 8 8 7 8 8

听到这里,不知道

总结

#include<stdio.h>
int main()
{int i = 8;printf("%d %d  %d \n", ++i, i,i--);return 0;
}
  1. 从 右往左 进行计算
  2. 对于后置++或者-- 来说,计算结果即为打印结果
  3. 对于变量 、前置++或者- - ,打印所有表达式计算完毕后 ,i 的结果

执行 i - - ,打印结果8 ;i 变为7
执行i, 打印结果 最终 i 的值
执行i++, 打印结果 最终i的值 ,i变为8

最终i的值为8

打印结果为 8 8 8

记得点赞+收藏噢

如果你觉得不错,欢迎点赞+收藏,感谢!

本文标签: C语言关于printf输出的奇怪事printf(“d d d d dn“ I