user-0 提问: i = i++

回复:
user: user-0
content: 引用 11 楼 Q446512799 的回复:都打起来了 都这么写打谁  唉，有人掉进了这个坑  搞得我也想一探究竟

user: user-1
content: 谁这么写打谁

user: user-1
content: 都打起来了 都这么写打谁

user: user-0
content: 引用 5 楼 棉猴 的回复:跟编译器有关系，VS2015的到的值是2 00E11F45  mov         eax,dword ptr [i]   00E11F48  mov         dword ptr [i],eax   00E11F4B  mov         ecx,dword ptr [i]   00E11F4E  add         ecx,1   00E11F51  mov         dword ptr [i],ecx   这是 i = i++; 对应的汇编语言，你可以看到，先将i的值保存到ecx中，然后对ecx保存的值加1，然后将加ecx的值保存到i中。 引用 6 楼 千梦一生 的回复:我的理解： 首先i = i++；如果要等于2，思考后得到的方案可能是： 先i++ 然后再i = i【自增之前的i】 详细如下：--------------------------------------------------- i = i++ 首先， = 和++运算，后者优先级高 step1： i++//这里毫无疑问返回1。并且产生了副作用 i变成了2【这个副作用的成立时间很关键】 step2： i = (i++的返回值)，即i = 1； --------------------------------------------------------------- 好了以上我们能确定的计算顺序有： step1：先计算i++的值，返回1。 step2：再计算i = （i++的返回值），【它本身返回i的值，但这里没有实际意义】 ---------------------------------------------------------------- 但问题出现了就是副作用的成立时间，C里面规定的是顺序点之前任何时候计算出来即可 所以：可能且满足标准的定义可以有： step1：先计算i++的值，返回1。 副作用，i 自增 = 2； step2：再计算i = （i++的返回值），【它本身返回i的值，但这里没有实际意义】，此时结果i = 1，因为（i++的返回值为1） 或者： step1：先计算i++的值，返回1。 step2：再计算i = （i++的返回值），【它本身返回i的值，但这里没有实际意义】 副作用，i 自增 = 2；，此时结果i = 2，因为自增 引用 7 楼 真相重于对错 的回复:这是标准未定义行为 未定义行为 1) 若对一个标量对象的副效应与另一个对同一标量对象的副效应相对无顺序，则行为未定义。 i = ++i + i++; // 未定义行为 i = i++ + 1; // 未定义行为 f(++i, ++i); // 未定义行为 f(i = -1, i = -1); // 未定义行为 引用 8 楼 qybao 的回复:[quote=引用 3 楼 ?Victor.?? 的回复:]   百度上也没有太正规的解释  有人这么说  i++表达式的值是1，i的值是2  ++i与之相反 i++的表达式的值是i，这个是毫无疑问的，要不然和++i有啥区别？否则一直以来的a[i++] =b; 这样的赋值，必然少一项a[i]，显然很多代码已经证明这是不可能的，a[i++] =b就是等价于a[i] =b，i=i+1，所以可见i++的表达式就是i，要不然a[i] 就变成a[i+1]了  i=i++ c++15以前是未定义行为，也就是没有规定等号左右两边的表达式的执行顺序（也就是有可能先把等号右边的表达式的值1赋给左边的i，再继续执行等号右边的i自增，这样的结果就是2） c++15以后规定赋值语句等号右边的表达式优先执行，所以c++15以后就像我上述分析的一样，先执行完等号右边，再把等号右边的表达式的值赋给等号左边的i    [/quote]  引用 9 楼 自信男孩 的回复:这样的问题不建议深究，有歧义，有异议那为什么还要写呢？给自己和别人找麻烦，让别人也疑惑。 所以，不建议写这样的代码～  嗯，谢谢各位大佬

user: user-2
content: 这样的问题不建议深究，有歧义，有异议那为什么还要写呢？给自己和别人找麻烦，让别人也疑惑。 所以，不建议写这样的代码～

user: user-3
content: 引用 3 楼 ?Victor.?? 的回复:百度上也没有太正规的解释  有人这么说  i++表达式的值是1，i的值是2  ++i与之相反 i++的表达式的值是i，这个是毫无疑问的，要不然和++i有啥区别？否则一直以来的a[i++] =b; 这样的赋值，必然少一项a[i]，显然很多代码已经证明这是不可能的，a[i++] =b就是等价于a[i] =b，i=i+1，所以可见i++的表达式就是i，要不然a[i] 就变成a[i+1]了  i=i++ c++15以前是未定义行为，也就是没有规定等号左右两边的表达式的执行顺序（也就是有可能先把等号右边的表达式的值1赋给左边的i，再继续执行等号右边的i自增，这样的结果就是2） c++15以后规定赋值语句等号右边的表达式优先执行，所以c++15以后就像我上述分析的一样，先执行完等号右边，再把等号右边的表达式的值赋给等号左边的i

user: user-4
content: 这是标准未定义行为 未定义行为 1) 若对一个标量对象的副效应与另一个对同一标量对象的副效应相对无顺序，则行为未定义。 i = ++i + i++; // 未定义行为 i = i++ + 1; // 未定义行为 f(++i, ++i); // 未定义行为 f(i = -1, i = -1); // 未定义行为

user: user-5
content: 我的理解： 首先i = i++；如果要等于2，思考后得到的方案可能是： 先i++ 然后再i = i【自增之前的i】 详细如下：--------------------------------------------------- i = i++ 首先， = 和++运算，后者优先级高 step1： i++//这里毫无疑问返回1。并且产生了副作用 i变成了2【这个副作用的成立时间很关键】 step2： i = (i++的返回值)，即i = 1； --------------------------------------------------------------- 好了以上我们能确定的计算顺序有： step1：先计算i++的值，返回1。 step2：再计算i = （i++的返回值），【它本身返回i的值，但这里没有实际意义】 ---------------------------------------------------------------- 但问题出现了就是副作用的成立时间，C里面规定的是顺序点之前任何时候计算出来即可 所以：可能且满足标准的定义可以有： step1：先计算i++的值，返回1。 副作用，i 自增 = 2； step2：再计算i = （i++的返回值），【它本身返回i的值，但这里没有实际意义】，此时结果i = 1，因为（i++的返回值为1） 或者： step1：先计算i++的值，返回1。 step2：再计算i = （i++的返回值），【它本身返回i的值，但这里没有实际意义】 副作用，i 自增 = 2；，此时结果i = 2，因为自增

user: user-6
content: 跟编译器有关系，VS2015的到的值是2 00E11F45  mov         eax,dword ptr [i]   00E11F48  mov         dword ptr [i],eax   00E11F4B  mov         ecx,dword ptr [i]   00E11F4E  add         ecx,1   00E11F51  mov         dword ptr [i],ecx   这是 i = i++; 对应的汇编语言，你可以看到，先将i的值保存到ecx中，然后对ecx保存的值加1，然后将加ecx的值保存到i中。

user: user-0
content: 引用 2 楼 六道佩恩 的回复:在同一个式子里对同一个变量操作两次，结果是不确定的，这要看编译器怎么编译了 我用新版gcc测试结果为1 老版gcc为2 vc++6.0为2 turbo C为2  哦，原来这样

user: user-0
content: 引用 1 楼 qybao 的回复:等式右边，先取i=1作为表达式的值，然后i自增变成2，然后再把表达式的值1赋给等号左边的i，所以i又变回1了 如果不理解我说的，先自己谷歌百度一下什么是表达式的值  百度上也没有太正规的解释  有人这么说  i++表达式的值是1，i的值是2  ++i与之相反

user: user-7
content: 在同一个式子里对同一个变量操作两次，结果是不确定的，这要看编译器怎么编译了 我用新版gcc测试结果为1 老版gcc为2 vc++6.0为2 turbo C为2

user: user-3
content: 等式右边，先取i=1作为表达式的值，然后i自增变成2，然后再把表达式的值1赋给等号左边的i，所以i又变回1了 如果不理解我说的，先自己谷歌百度一下什么是表达式的值