一个有趣的C语言问题:s = (++i) + (++i) + (++i)

今天看到有人提了这么个问题;

i=3,s=0

s=(++i)+(++i)+(++i )

为什么结果是s=16,i=6呢

初一看,我想结果不应该是15(4+5+6)吗,是他搞错了吧,保险起见,我决定用编译器运行一下,看一下结果,先是用VC是了一下,结果确实没错,

会不会是编译器问题,不行,我再试试其他编译器,换了codeblocks试了一下:

那么DevC++呢,我再试了一下:

结果还是这样,好吧,我放弃了,结果就应该是16,那么这又是为什么呢?

我定下心来,仔细想了想,想了片刻,觉得应该是这样:

i = 3, 运行++i之后 i = 4; 在运行++i之后 i = 5;在求出了+所需的两个操作数后,计算出两个操作数的和放到寄存器中,这两个操作数所在的位置都是当前i的位置,所以现在的和为5+5=10,放到寄存器中;现在对最后一个+,有了左操作数,右操作数还不确定,先求出右操作数++i,运算之后i = 6;所以最终的结果是10+6=16

为了验证自己的猜想,我写了个小程序,求了一下s = (++i) + (++i)的值,按照猜想,这个结果应该是10,测试了一下,确实是

刚准备把自己的想法讲给别人听的时候,有遇到了一个新的问题,提出这个问题的同学说,用VS2013运行了一下,结果是18 !!!当时我就震惊了,难道刚刚的理解有问题???抱着怀疑的态度,我用VS2013运行了一下,结果如下:

确实是这样的,看到这个结果,我又一头雾水了。。。

就在我一筹莫展之时,我突然想起,我们不是正在学微机原理和汇编吗(虽然现在也没讲多少东西),一个念头涌上我的心头,要不看看他们编译之后生成的汇编代码,看看能不能看出点名堂(汇编只接触过一点点)。怀着试一试的心态,我看了一下汇编的代码:

这一看,好像还真看出了点眉目来了,通过汇编代码,我们可以发现,VC和VS的编译方式是不相同的:

VC是这么处理的,在进行加法运算时,求出了左值和右值之后,就求出他们的和,再进行下一步操作;

VS是这样处理的,在多个式子相加的时候,先求出各个因式的值,最后一起执行加法操作(也就是执行++i,++i,++i之后,再求他们的和,所以是18);

这里我们还应该注意一点:对(++i)进行操作的时候(假设地址p出存放的是i的值),我们用的还是地址p处的值,也就是与i相关的操作执行之后(要考虑优先级)i的值。

跟同学讲了一下我的想法,这下终于解释清楚了这个问题,终于可以舒一口气了。真是个有趣的问题。

时间: 2024-12-21 18:52:47

一个有趣的C语言问题:s = (++i) + (++i) + (++i)的相关文章

Nim Game,一个有趣的游戏,也是一道入门算法题。

Nim Game,其实很多人都玩过.其实就是我们玩的划线游戏. 一张纸上,画若干条线,双方一人划一次,每次划掉1~3条线.可以选择画1条,也可以划2条,也可以3条.具体划去几条线完全看自己的策略.谁划掉最后一条线,就是赢家. 如上图,蓝方获胜. 正在看这篇文章的你一定是一个聪明人,每一步都是最优解,而你的对手,也跟你一样聪明,每步都是最优的解法. 现在你作为先手,在线条总数为多少的时候,你必赢呢,又在多少的时候必输呢? 可不可以用一个函数来判断在线条总是为x时你的输赢情况呢?这样你以后跟别人玩这

12个有趣的C语言问答(详解)

本文参照博文<12个有趣的C语言问答>,在原文的基础上增加来对应的知识点的详细介绍. 1 gets()方法 Q:下面的代码有一个被隐藏的问题,你能找到它吗? 1 #include <stdio.h> 2 3 int main(void) 4 { 5 char buff[10]; 6 memset(buff, 0, sizeof(buff)); 7 gets(buff); 8 printf("%s\n", buff); 9 10 return 0; 11 } A:

一个有趣的js隐式转换的问题

一个有趣的js隐式转换的问题 在chrome的控制台中打印一下表达式 [] + {} //结果为 [object object] 然后调整顺序打印 {} + [] //结果为 0 然后将两个表达式组合一下 {} + [] === [] + {} //true wtf??? 原理解释如下: 一般的类型转换的时候, 面对 + , 首先调用 valueOf^[1]进行转换, 如果转换的结果不是 基本类型, 那么采用 toString() 方法进行转换, 所以 []+{} //结果Wie [object

关于java除法的一个有趣例子。

今天逛贴吧的时候偶然发现吧友的一个有趣例子. public class Demo{     public static void main(String[]args){         System.out.println(24/0);  //会抛byzero异常         System.out.println(24.0/0.0) //可以输出,输出为Infinity:     } } 目前对于第二句为什么不会报byzero异常也不知道.先做个标记.理解了再补充上.

一个有趣的SQL Server 层级汇总数据问题

看SQL Server大V宋大侠的博客文章,发现了一个有趣的sql server层级汇总数据问题. 具体的问题如下: parent_id emp_id emp_name total_amout     NULL 2 Andrew 200     2 1 Nancy 100     2 3 Janet 120     3 4 Michael 80     1 5 Robert 50     每个员工的总销售额=自己的销售额+其下级员工的总销售额,     比如:     Andrew = 200_

一个有趣的Timer应用

import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TraditionalTimerTest { static int count; public static void main(String[] args) { class MyTimerTask extends TimerTask { @Override public void run() { count = (cou

一个有趣的现象(苹果的bug Or 坑?),关于区分真机和模拟器的预编译宏

TARGET_IPHONE_SIMULATOR和TARGET_OS_IPHONE 是苹果的两个宏定义, 在真机sdk中位于ios->usr/include/targetconditionals.h中, 在模拟器sdk中位于simulator->usr/include/targetconditionals.h中 (笔者此时使用的xcode版本为5.1,sdk版本是7.1) 仔细看其模拟器sdk中的定义: #define TARGET_OS_IPHONE            1 #define

转:做一个有趣的有意思的人

(本文转自 现代简明魔法 在此特别表示感谢) 今天吃午饭时,听到隔壁说菜上面有虫的事,突然想起了去年离职的技术总监林工.那就水点破事,写个小短篇吧. 如果是林工的话,他肯定会说,幸好是发现一条虫,而不是半条.脑补了一下,然后自己就乐呵乐呵了.他是个很有趣的人,很有意思的人,首先没啥领导架子,然后很关怀人,说话很风趣,平时就捣鼓一些在一般人眼里觉得奇怪的东西,比如树莓派,模型,自己设计组装亚克力架什么的.新年红包总是有惊喜,比如是一张老毛子再加一张10元葡币什么的(我们珠海这里很近澳门)--反正跟

当filter使用函数而非选择器来过滤元素时的一个有趣的地方

JQuery官方API关于filter方法的介绍有这么一个实例: <div id="first"></div> <div id="second"></div> <div id="third"></div> <div id="fourth"></div> <div id="fifth"></div