首页
社区
课程
招聘
[旧帖] [求助]C语言的自增 0.00雪花
发表于: 2010-12-21 10:36 2105

[旧帖] [求助]C语言的自增 0.00雪花

2010-12-21 10:36
2105
int a ,b,c,d;
        a = b = 5;
        c =(++a)+(++a)+(++a);
        d =(b++)+(b++)+(b++);
        printf("%d,%d,%d,%d,%d,%d",a,b,c,d);

在VS2010中测试为8,8,24,15

前面的a值和b值在运算完了之后值为8我能懂。
但是后面的c=24不懂。 我认为,c = 6+7+8
d=15也不能理解。我认为,d=5+6+7

求助高人指点,我的理解错在哪里。并告诉正确的计算方式。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (24)
雪    币: 45
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
首先明确优先级:++ > +

c =(++a)+(++a)+(++a);  ==>  ++a; ++a; ++a; c = a + a + a;    //  c = 24, a = 8
d =(b++)+(b++)+(b++);  ==>  d = b + b + b;  b++; b++; b++;   //  d = 15, b = 8

这么写只是为了方便理解,LZ可自行调试一下
2010-12-21 10:53
0
雪    币: 20
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
你说了 ++ 优先级大于 +
那d =(b++)+(b++)+(b++);   也应该是先做自增预算啊.先做三个 b++,然后做加法.
2010-12-21 10:57
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
与编译器有关,不同的编译器结果不一样.
2010-12-21 11:03
0
雪    币: 36
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
这在C语言中属于“未定义行为”,出现任何运行结果都是允许的(包括崩溃!)
c =(++a)+(++a)+(++a);//同一级的括号运算优先级是相等的, 这3个括号的运算优先级是平等的.所以这3个括号内的表达式计算顺序完全是不确定的(编译器甚至可能搞并行优化).
2010-12-21 11:28
0
雪    币: 1325
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
为什么要 深究这个 ++i与i++
2010-12-21 11:46
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
完全同意,这跟C语言中定义的序列化点有关。
C语言在两个序列化点之间,只允许写同一变量一次,并且如果既读又写,那么一定是只能用读出来的值来计算要写进去的值。(很含糊吧)
所谓序列化点包括
a;b;(分号)保证 a在b前执行
if(a){b}  while(a){b}  保证 a在b前执行
(a,b)   (逗号运算符,与函数调用的分隔符不一样) 保证a在b前执行
a=a+b; 可以,符合读出来的值用来计算写入的值
a && b 保证a在b前执行
a || b 也是一样
等等
特别注意的是自增、赋值、加减乘除、位与或等等都不是序列点,
这个不仅仅是优先级的问题,加括号也不能改变(其实括号就只是用来强制优先级,但是优先级规定的结合性,而不是哪个先计算,这与我们平时的自然语言习惯有不同)

这里的“在……之前”只是从效果上来说,编译器优化是允许的(意即除了代码变快不能有别的可观察的区别)

至于未定义行为,标准要求编译器自行选择合理(但没有规定什么叫合理 )的行为。
违反了规定,编译器可以给警告(要打开关,比如gcc的-Wall -W就会警告这种错误),也可以不给(因为很难检测)
我记得Java就规定了一大堆的东西,比如a+b中a要在b前计算。(我不熟悉Java)
2010-12-21 12:06
0
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
debug版和release版的区别是 ,他们断句的粒度不一样,我们知道 i++,是等这一行执行完了才加一,所以debug版和release版的结果也不一样.
2010-12-21 12:54
0
雪    币: 411
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
http://bbs.pediy.com/showthread.php?t=61272&highlight=%E8%87%AA%E5%A2%9E
2010-12-21 12:56
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
10
c =(++a)+(++a)+(++a);

a 先自增了三次,然后再相加的。
所以
c = 8+8+8 // 在赋值给c之前,a的值是8

同样的

d =(b++)+(b++)+(b++);

先把三个 b 相加,然后b再自增三次。

d=5+5+5 // 在赋值给d之后,b的值是8

以上的行为是在VC编译中的情况。
在GCC中,比较有意思:
  a = 5;

  c =(++a)+(++a)+(++a);

对应的反汇编代码如下:
004013A6	movl   $0x5,(%esp)    a=5
004013AD	incl   (%esp)               ++a -> a=6
004013B0	incl   (%esp)               ++a -> a=7
004013B3	mov    (%esp),%eax   eax=7
004013B6	add    %eax,%eax      eax=14=7+7
004013B8	incl   (%esp)               ++a -> a=8
004013BB	add    (%esp),%eax   eax=22=14+8 -> c=22

也就是说在GCC中是分两步进行保存的,a 自增两次之后,中间结果保存给c,然后c再和第三次自增的结果相加。结果是22
另外:
printf("%d,%d,%d,%d,%d,%d",a,b,c,d);

%d 的个数和后面的参数列表不符,多了两个,实际会多输出栈上的数据。
2010-12-21 13:10
0
雪    币: 596
活跃值: (449)
能力值: ( LV12,RANK:320 )
在线值:
发帖
回帖
粉丝
11
这种题,好像只有蛋疼的大学考试还会有..
2010-12-21 13:12
0
雪    币: 163
活跃值: (75)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
功底相当扎实!
2010-12-21 15:59
0
雪    币: 99
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
进来学习了,这些天找工作,笔试题大多都有这种题,真是有点懵了- -!
2010-12-21 16:03
0
雪    币: 45
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
关于前++和后++,我不好描述, 你自己理解下。
2010-12-22 02:21
0
雪    币: 19
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
真是让人蛋疼的结果啊。。。
2010-12-22 09:05
0
雪    币: 401
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
汗,似乎每个人初学C语言时都会问这个问题,我当初也是……

如果没记错的话C99标准说这种情况是未定义的(undefined),所以到底会发生什么样的结果是不确定的,甚至在不同的编译器下编译运行的结果也是不相同的,没必要去理会这个问题了。
2010-12-24 11:53
0
雪    币: 239
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
看了此篇,深刻理解C自增自减了
2010-12-24 11:58
0
雪    币: 239
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
这个写得很好~~~
2010-12-24 11:59
0
雪    币: 36
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
19
很麻烦啊,一般不这样用
2010-12-24 16:56
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
我一般是这么记着的,++i是先自增再进行运算,i++是运算后再自增。
2010-12-25 11:21
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
这个确实。。。没什么用但是对笔试什么的很有用  mark 了
2011-5-24 00:22
0
雪    币: 201
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
22
不知道考試為什麼靠這種蛋疼的題
2011-5-26 02:14
0
雪    币: 245
活跃值: (93)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
23
没事钻研这个干啥
2011-5-28 01:19
0
雪    币: 17
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cpe
24
不同的编译器处理的结果也不一样
2011-5-28 02:58
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
7楼兄台所言极是。
2011-6-2 14:43
0
游客
登录 | 注册 方可回帖
返回
//