| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2576 人关注过本帖
标题:请教VC++中 ++的问题
只看楼主 加入收藏
rswl3322
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2016-10-4
收藏
得分:0 
谢谢各位的帮助,明白了,不同的编译器处理方法不一样,只能记住这种处理方法,没多少道理可讲
2016-10-05 11:26
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:0 
以下是引用书生牛犊在2016-10-5 10:46:45的发言:
我们唯一可以确定的就是这行代码执行过后a=8.

也不能,因为中间没有序列点,此a可能非彼a,也就是执行一个a++时它不知道还有另外的a++,可能不去更新修改后的a值。

当然,以上都没有意义,未定义行为 和 实现定义行为 不一样,后者指有确定的结果,只是各个编译器的结果可能不一致,无法移植;而前者,对同一个编译器都可能不一样,第一次运行可能给你72个处女,第二次运行可能直接爆了你。
2016-10-05 12:13
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 12楼 rjsp
突然想起汇编的相关知识。是关于计算机如何执行加法运算的
是不是说计算机内部做这些加法运算的时候 它不是在这个元素a的位置计算的,它是把数据复制到寄存器(还是什么,汇编语言里的,我看过,但没学),在寄存器的位置做这些运算。。如果这样的话,确实不可以保证p=++a1 + ++a2 + ++a3执行过后a==8,因为谁也不知道那三个a传递进寄存器的时间顺序.可能三个a同时传进去,那就都是5,自增完了也只是6。  

。。。幸亏现实编程当中不会用到这种 几个自增的运算。。

φ(゜▽゜*)♪
2016-10-05 14:53
ehszt
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:40
帖 子:1745
专家分:3216
注 册:2015-12-2
收藏
得分:0 
什么叫没有序列点,难道不是依次传进去的吗?不懂,我也认为最后一定为8。

[此贴子已经被作者于2016-10-5 15:40编辑过]

2016-10-05 15:37
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 14楼 ehszt
p= ++a1 + ++a2 + ++a3

你可以试着这么理解:因为计算机在执行几个++a分别调用了不同的寄存器(相当于函数),由于我们不知道哪个++a会被先执行,甚至可能几个++a 是同时执行的,那么
传递进每一个++a的数值都是5,计算返回的结果又都写入到a中,这时写了3个6,执行结果a==6  而如果程序是一个一个运行,++a1的的运行结果就是往a上写6,之后执行++a2的结果就会是7,再执行++a3的结果就等于a==8.  类似的如果++a1 和++a2同时进行,而++a3被放到后面的话a==7.




φ(゜▽゜*)♪
2016-10-05 15:48
ehszt
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:40
帖 子:1745
专家分:3216
注 册:2015-12-2
收藏
得分:0 
回复 15楼 书生牛犊
为什么会同时执行?我觉得这样的情况不会发生,汇编的话也是一条一条的运行。
#include <stdio.h>
main()
{
   int a=1,b;
   for(int i=0;i<300;i++)
   {
   b=(++a)+(++a)+(++a);
   printf("%d %d\n",a,b);
   a-=3;
   }
}
这个程序300次运行结果均相同。

[此贴子已经被作者于2016-10-5 15:56编辑过]

2016-10-05 15:53
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 16楼 ehszt
我用DEV,b==10,a==4.和你的一样。。。
 未定义行为,指的是C语言标准没有定义的。但是没说各家的编译器没有定义。

就好像下面这个程序
int fun(int n){
printf("%d ",n);
if(n==1)return 1;
if(n==2)return 1;
return fun(n-1)+fun(n-2);
}
  按道理说没规定先执行fun(n-1)还是fun(n-2),但是在我的的环境下他就是先递归执行了fun(n-1),然后返回上一层,再执行fun(n-2),并没有出现过不规律的现象。
return fun(n-1)+fun(n-2);
和 int temp=fun(n-1);temp+=fun(n-2);return temp;
输出的结果一样。 但是就是没有规定说加号左边的式子必须先执行。而后者则是可以确信不管在什么环境下,他都是先执行fun(n-1)后执行fun(n-2)的。
   
  ------------------------------------
在我看来,之所以不规定加号左右两边的式子哪个先执行就是为了让程序能够被多线程并行处理。而我们这些初学者所使用的编译器真的会生成一个多线程的exe吗?恐怕不能吧,我估摸着大多是单线程的。



[此贴子已经被作者于2016-10-5 16:37编辑过]


φ(゜▽゜*)♪
2016-10-05 16:33
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:0 
以下是引用ehszt在2016-10-5 15:37:53的发言:
什么叫没有序列点,难道不是依次传进去的吗?不懂,我也认为最后一定为8。

序列点就是“副作用”必须发生的地方,例如
a = 5; // 这个表达式副作用是a赋值为5,这个表达式返回5
到这里a一定等于5,因为分号是个序列点
++a; // 这个表达式副作用是a的值变为6,这个表达式返回6
到这里a一定等于6,因为分号是个序列点
++a; // 这个表达式副作用是a的值变为7,这个表达式返回7
到这里a一定等于7,因为分号是个序列点


a = 5;
++a + ++a;
因为没有序列点,无法确定“a的值变为多少”在何时发生(跟汇编没关系,而是发生在生成汇编代码之时)。如果是“实现定义”的话,那么a的值可能是6,可能是7;整个表达式的值可能是 12、13、14 之一。
“未定义”的话,一切都有可能,就不仅仅只是改改a值

手机打字不方便,就不一一回复了
2016-10-05 20:57
creat_cc
Rank: 2
等 级:论坛游民
帖 子:2
专家分:18
注 册:2016-9-19
收藏
得分:3 
这个看编译器心情,这句话好棒,我喜欢。
2016-10-05 22:39
快速回复:请教VC++中 ++的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020863 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved