[C语言]关于printf输出的奇怪事:printf(“%d %d %d %d %d “, ++i, --i, i++,i--, i),printf(“%c%c “,*p++,*p++)的结果分析

Posted 凌星An

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C语言]关于printf输出的奇怪事:printf(“%d %d %d %d %d “, ++i, --i, i++,i--, i),printf(“%c%c “,*p++,*p++)的结果分析相关的知识,希望对你有一定的参考价值。

题目

打开这篇文章,屏幕前的你一定也是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 %d “, ++i, --i, i++,i--, i),printf(“%c%c “,*p++,*p++)的结果分析的主要内容,如果未能解决你的问题,请参考以下文章

c语言中,printf,print,input,都表示输出,他们有啥区别

c语言输入一个整数,用递归算法将整数倒序输出.

c语言一个关于printnum的问题

c语言中怎样在输出语句printf中输出双引号

print、printf、println的区别

关于C语言printf的使用,为何输出乱码