[C语言]关于printf输出的奇怪事:printf(“%d %d %d %d %d\n“, ++i, --i, i++,i--, i),printf(“%c%c\n“,*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

记得点赞+收藏噢

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

  • 21
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值