关于C语言的printf输出问题
前端面试的时候老总居然问这个问题,有点震惊……
#include <stdio.h>
#include <stdlib.h>
void main() {
int i = ;
printf("%d,%d,%d,%d,%d,%d\n", i,i++,++i,i--,i++,--i);
system("pause");
}
作为一个以前压根没深入研究过C语言运行机制的人,这个问题真是难住我了
如果你的回答是输出
,,,,,
恭喜你跟我错得一样,老总说这跟语言没关系,所有语言的思路都一样……但是明明JS的运行结果就是上面那个嘛……
在VS下,运行结果是
,,,,,
震惊之余,看了下反汇编的代码
int i = ;
00DF3C0E mov dword ptr [i],
printf("%d,%d,%d,%d,%d,%d\n", i,i++,++i,i--,i++,--i);//看看结果是从右往左开始运算
00DF3C15 mov eax,dword ptr [i]
00DF3C18 sub eax,
00DF3C1B mov dword ptr [i],eax //--i,i=0
00DF3C1E mov ecx,dword ptr [i]
00DF3C21 mov dword ptr [ebp-0D0h],ecx //将i复制一份到 dword ptr [ebp-0D0h]这个地址,0
00DF3C27 mov edx,dword ptr [i]
00DF3C2A add edx,
00DF3C2D mov dword ptr [i],edx //i++,i=1
00DF3C30 mov eax,dword ptr [i]
00DF3C33 mov dword ptr [ebp-0D4h],eax //将i复制一份到 dword ptr [ebp-0D4h]这个地址,1
00DF3C39 mov ecx,dword ptr [i]
00DF3C3C sub ecx,
00DF3C3F mov dword ptr [i],ecx //i--,i=0
00DF3C42 mov edx,dword ptr [i]
00DF3C45 add edx,
00DF3C48 mov dword ptr [i],edx //++i,i=1
00DF3C4B mov eax,dword ptr [i]
00DF3C4E mov dword ptr [ebp-0D8h],eax //将结果复制一份到dword ptr [ebp-0D8h]这个地址,1
00DF3C54 mov ecx,dword ptr [i]
00DF3C57 add ecx,
00DF3C5A mov dword ptr [i],ecx //i++,i=2
00DF3C5D mov esi,esp
00DF3C5F mov edx,dword ptr [i] //edx = 2
00DF3C62 push edx //2入
00DF3C63 mov eax,dword ptr [ebp-0D0h] //eax = 0
00DF3C69 push eax //0入
00DF3C6A mov ecx,dword ptr [ebp-0D4h] //ecx = 1
00DF3C70 push ecx //1入
00DF3C71 mov edx,dword ptr [i] //edx = 2
00DF3C74 push edx //2入
00DF3C75 mov eax,dword ptr [ebp-0D8h] //eax = 1
00DF3C7B push eax //1入
00DF3C7C mov ecx,dword ptr [i] //ecx = 2
00DF3C7F push ecx //2入
00DF3C80 push 0DF59CCh
00DF3C85 call dword ptr ds:[0DF9114h]
00DF3C8B add esp,1Ch
00DF3C8E cmp esi,esp
00DF3C90 call __RTC_CheckEsp (0DF1136h)
虽然其中部分操作不知道是做什么用的,但是看最下面的数字,可以发现就是最终的输出结果
从其中可以分析出,在运算过程中,往内存中写入了多个新的值(比如新产生的dword ptr [ebp-0D0h])
碰到i++,i--的时候,会从一个新的内存地址中取值
碰到++i,--i,i的时候,会从最初的内存地址中取值,也就是获取i计算的最终值
那么,我们可以发现,在计算i++,i--之前,i的结果会缓存到内存中,以便后面使用
这样,结果就迎刃而解了
PS:
运算是自右往左的方向计算的,压栈也是
如果我们在最后面再加一个参数i,会发现反汇编的代码最开始的部分没变,也就是说,首先会计算自增,自减部分
如果在其中加入i+1这样的操作,会发现这部分代码是在压栈的同时计算的
关于C语言的printf输出问题的更多相关文章
- 贪吃蛇游戏(printf输出C语言版本)
这一次我们应用printf输出实现一个经典的小游戏—贪吃蛇,主要难点是小蛇数据如何存储.如何实现转弯的效果.吃到食物后如何增加长度. 1 构造小蛇 首先,在画面中显示一条静止的小蛇.二维数组canva ...
- [转]C语言文件输入/输出ACM改进版(freopen函数)
C语言文件输入/输出ACM改进版(freopen函数) 2009年5月27日 10:379,457 浏览数发表评论阅读评论 文章作者:姜南(Slyar) 文章来源:Slyar Home (www. ...
- C语言中格式化输出的转换说明的fldwidth和precision解析
首先说什么是C语言的格式化输出,就是printf和它的几个变种(grep -E "v?(sn|s|f)printf").像这些函数都有一个参数format,format中可以加点转 ...
- C语言的printf输出格式控制
C语言的printf输出格式控制 printf大家都耳熟能详,但是能真正将其用法弄透的估计很少见. 转一篇,改天整理. 1.转换说明符 %a(%A) 浮点数.十六进制数字和p-(P-)记数法( ...
- IOS学习笔记07---C语言函数-printf函数
IOS学习笔记07---C语言函数-printf函数 0 7.C语言5-printf函数 ------------------------- ----------------------------- ...
- C 语言实例 - 循环输出26个字母
C 语言实例 - 循环输出26个字母 循环输出 个字母. 实例 #include <stdio.h> int main() { char c; for(c = 'A'; c <= ' ...
- YTU 2416: C语言习题 成绩输出
2416: C语言习题 成绩输出 时间限制: 1 Sec 内存限制: 128 MB 提交: 1111 解决: 417 题目描述 输入n(<=10)个学生的姓名.学号和成绩,将其中不及格者的姓 ...
- printf 输出浮点数
在测试printf函数输出结果时,写了如下代码: /** * printf:格式化输出函数 * printf函数不会按照格式控制而对数据类型进行转换,不管三七二十一, * 抓到二进制数据就按照格式控制 ...
- C/C++编程笔记:C语言基础printf()和scanf()函数,大学入门知识
在解释这两个函数之前,为了方便大家更容易理解,我们先来讲讲下面的这幅图. 这个图中的例子其实很简单,我们就是把题目通过输入设备(例如键盘鼠标)传输到计算机中,然后让计算机进行运算得出结果,再然后把 ...
随机推荐
- C#配置文件管理
最近在做项目的过程中用到配置文件,本文简要说明本人在项目过程中是如何使用配置文件的,目的是加深自己对配置文件管理的理解,以便在下次使用时能做到轻松自如. 配置文件,顾名思义,是用户在使用系统或者软件时 ...
- Daily Scrum – 1/19
Meeting Minutes 绑定了快捷键: 改良了user course: 修了一系列Bug: 准备进行演示 Progress part 组员 今日工作 Time (h) 明日计划 Time ...
- Codeforces Round #167 (Div. 2) D. Dima and Two Sequences 排列组合
题目链接: http://codeforces.com/problemset/problem/272/D D. Dima and Two Sequences time limit per test2 ...
- 阿里面试回来,想和Java程序员谈一谈(转载)
引言 其实本来真的没打算写这篇文章,主要是LZ得记忆力不是很好,不像一些记忆力强的人,面试完以后,几乎能把自己和面试官的对话都给记下来.LZ自己当初面试完以后,除了记住一些聊过的知识点以外,具体的内容 ...
- win8 配 jdk
Win8配置jdk 1.7环境变量 环境:win8(32位)64位差不多 jdk1.7 1.右击计算机-属性-高级系统设置-高级-环境变量,弹出“环境变量”对话框,主要是改下面的环 ...
- 用SQL打印乘法口诀表
--用SQL打印出乘法口诀表 declare @i int ,@j int --@i是乘法口诀的行数 --一共九行 begin --每次都是从1*开始,j每循环一次递增 )--print每次输出都会换 ...
- 【poj2983】 Is the Information Reliable?
http://poj.org/problem?id=2983 (题目链接) 一个SB错误TLE了半个小时... 题意 一条直线上有n个点,给出m条信息,若为P则表示点A在点B的北方X米,若为V则表示A ...
- BZOJ2302 [HAOI2011]Problem c
Description 给n个人安排座位,先给每个人一个1~n的编号,设第i个人的编号为ai(不同人的编号可以相同),接着从第一个人开始,大家依次入座,第i个人来了以后尝试坐到ai,如果ai被占据了, ...
- RegexBuddy正则表达式工具
RegexBuddy非常的好用,而且还能生成.net的代码. 我们在使用正则匹配时,毕竟.net提供的方法中,对于多行匹配就不能用单纯的正则去实现,而我们需要把它转换成相应的类库方法进行实现. 那么R ...
- jsp学习(二)
jsp运行原理 当服务器上的一个jsp页面被第一次请求标记时,服务器上的jsp引擎首先将jsp页面文件转译成一个Java文件,并编译这个java文件生成字节码文件,然后执行字节码文件响应客户的请求. ...