已掉线,重新登录

首页 > 绿虎论坛 > 历史版块 > 编程 > C/C++ > 讨论/求助

标题: 练习C语言自增运算卡壳了

作者: @Ta

时间: 2019-10-30

点击: 9362

看到一段代码,然后自己拿来跑了下
void main()
{
	int a = 0, b = 0;
	printf("%d,%d,%d \n",a++,++a, a++); //2 2 0  //2 3 0
	getchar();
}

按我自己的理解应该输出2 2 0,但是不明白为何输出的结果是2 3 0
欢迎发表自己的看法,看我自己能不能找出我哪里理解错了

[隐藏样式|查看源码]


『回复列表(11|隐藏机器人聊天)』

1.

php 的话是0 2 2...斗图专属版

(/@Ta/2019-10-30 20:21//)

2. 萌新表示不懂c,难道是中间的a膨胀了??
(/@Ta/2019-10-30 23:17//)

3.
(/@Ta/2019-10-31 09:37//)

4. @Curtion,赞,收益颇多。
结合文中的描述也对i++有了更清晰的认识
-我认为“i++是先取i的值,用这个值代入表达式”才更简单明了
以前我对它们的概念就是先参与运算再自增,对值得改变一直很模糊
在i=i++哪儿卡了好一会儿,直到自己模拟了一下
  3.i=i++
  先取i得值代入表达式计算0+0=0
  再把i+1=1
  此处i的值应该被改变
这时我再去看上面那句话才明白了他所说的是此处的i被改变是不合理的。

但是,如果离开那上面那句概念,i本身是个变量,顺序执行后被修改这我认为这也应该是合理的

不过,在跟过两种组合的汇编后感觉会带来不好确定的变数,理解起来也更复杂

--所以不知道能否运用在一些加密过程增加理解难度

综上,从简单明了的角度我还是认为前面的概念比较合理

-临时所感,有错望指正
(/@Ta/2019-10-31 19:50//)

5. @000,在Release中得到的值是1,1,0.
现在对编译过程还不了解。。
不过,看来这样定义的不同问题确实存在
(/@Ta/2019-10-31 20:02//)

6.

@user,所以说编写易维护的代码才是首要的 不要直接使用++了 斗图专属版

(/@Ta/2019-10-31 22:31//)

8. 只觉得应该是输出
0 2 2
a最终值为3
(/@Ta/2019-11-01 14:39//)

9. @泰戈尔会游泳,c中函数参数都是从右往左开始计算的,原因是啥我也忘了。至于最终值,在看了release版后,才认为更合理,两种符号在同一语句中最终结果就是+1。

以前想明白调试模式下自增的过程原因,现在回头看就显得没有意义
(/@Ta/2019-11-04 06:29//)

10.

@user,看起来结果跟编译器的代码生成方式有关。我用GCC 5.4编译这个代码,无论优化等级开到多少,结果都是2,3,0
-O0是没有任何优化(相当于Debug模式),-O3是最高等级优化。

# gcc -O0 main.c -o main; ./main
2,3,0
# gcc -O1 main.c -o main; ./main
2,3,0
# gcc -O2 main.c -o main; ./main
2,3,0
# gcc -O3 main.c -o main; ./main
2,3,0
# gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
(/@Ta/2019-11-04 07:06//)

11.

-O0优化下生成的汇编代码(Intel语法):

# gcc -O0 -c -g main.c; objdump -S -M intel ./main.o

./main.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
#include <stdio.h>
void main()
{
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   48 83 ec 10             sub    rsp,0x10
    int a = 0, b = 0;
   8:   c7 45 f8 00 00 00 00    mov    DWORD PTR [rbp-0x8],0x0
   f:   c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0
    printf("%d,%d,%d \n",a++,++a, a++); //2 2 0  //2 3 0
  16:   8b 55 f8                mov    edx,DWORD PTR [rbp-0x8]
  19:   8d 42 01                lea    eax,[rdx+0x1]
  1c:   89 45 f8                mov    DWORD PTR [rbp-0x8],eax
  1f:   83 45 f8 01             add    DWORD PTR [rbp-0x8],0x1
  23:   8b 45 f8                mov    eax,DWORD PTR [rbp-0x8]
  26:   8d 48 01                lea    ecx,[rax+0x1]
  29:   89 4d f8                mov    DWORD PTR [rbp-0x8],ecx
  2c:   8b 75 f8                mov    esi,DWORD PTR [rbp-0x8]
  2f:   89 d1                   mov    ecx,edx
  31:   89 f2                   mov    edx,esi
  33:   89 c6                   mov    esi,eax
  35:   bf 00 00 00 00          mov    edi,0x0
  3a:   b8 00 00 00 00          mov    eax,0x0
  3f:   e8 00 00 00 00          call   44 <main+0x44>
}
  44:   90                      nop
  45:   c9                      leave
  46:   c3                      ret
(/@Ta/2019-11-04 07:57//)

12. @老虎会游泳,嗯,我前几天还在想GCC 中该如何实现VS 里的release模式,现在明白了。
(/@Ta/2019-11-06 23:01//)

回复需要登录

9月5日 19:41 星期五

本站由hu60wap6驱动

备案号: 京ICP备18041936号-1