免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 2692 | 回复: 12
打印 上一主题 下一主题

一个C程序问题, 高手请指点. [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-07-01 18:45 |只看该作者 |倒序浏览
#include <stdio.h>

int main()
{
        int i = 3, j, k;

        j = i++;
        k = ++i;

        printf("i = %d, j = %d, k = %d\n", i, j, k);
        printf("%d\n", -i++);
        printf("%d, %d, %d\n", i, i++, i++);

}

程序如上.
编译:
[root@localhost 2-5]# gcc -o 2-5 2-5.c

运行:
[root@localhost 2-5]# ./2-5
i = 5, j = 3, k = 5
-5
8, 7, 6
[root@localhost 2-5]#

请问结果 8,7,6 怎么得来的?请解释一下.....

论坛徽章:
0
2 [报告]
发表于 2009-07-02 03:37 |只看该作者
编译器的问题,在MS VC上,如果是RELEASE版,最后一行打印的是6, 6, 6。如果是DEBUG版,打印的是8,7,6.

下面是GCC编译出来的汇编代码,可以看出在第三个PRINTF时候,I是被改了之后,又传给了RPINTF. 注意看2和3之间。

        .file        "2-5.c"
        .section        .rodata
.LC0:
        .string        "i = %d, j = %d, k = %d\n"
.LC1:
        .string        "%d\n"
.LC2:
        .string        "%d, %d, %d\n"
        .text
.globl main
        .type        main, @function
main:
        leal        4(%esp), %ecx
        andl        $-16, %esp
        pushl        -4(%ecx)
        pushl        %ebp
        movl        %esp, %ebp
        pushl        %ecx
        subl        $36, %esp
        movl        $3, -8(%ebp)
        movl        -8(%ebp), %eax
        movl        %eax, -12(%ebp)
        addl        $1, -8(%ebp)
        addl        $1, -8(%ebp)
        movl        -8(%ebp), %eax
        movl        %eax, -16(%ebp)
        movl        -16(%ebp), %eax
        movl        %eax, 12(%esp)
        movl        -12(%ebp), %eax
        movl        %eax, 8(%esp)
        movl        -8(%ebp), %eax
        movl        %eax, 4(%esp)
        movl        $.LC0, (%esp)
1        call        printf
        movl        -8(%ebp), %eax
        negl        %eax
        addl        $1, -8(%ebp)
        movl        %eax, 4(%esp)
        movl        $.LC1, (%esp)
2        call        printf
        movl        -8(%ebp), %edx  
        addl        $1, -8(%ebp)
        movl        -8(%ebp), %eax
        addl        $1, -8(%ebp)   
        movl        %edx, 12(%esp)
        movl        %eax, 8(%esp)
        movl        -8(%ebp), %eax
        movl        %eax, 4(%esp)
        movl        $.LC2, (%esp)
3        call        printf
        addl        $36, %esp
        popl        %ecx
        popl        %ebp
        leal        -4(%ecx), %esp
        ret
        .size        main, .-main
        .ident        "GCC: (GNU) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)"
        .section        .note.GNU-stack,"",@progbits

[ 本帖最后由 accessory 于 2009-7-2 03:46 编辑 ]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
3 [报告]
发表于 2009-07-02 07:51 |只看该作者
原帖由 accessory 于 2009-7-2 03:37 发表
编译器的问题,

是楼主代码的问题,他的那个代码行为本来就是不确定的/未定义的。

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:57:09
4 [报告]
发表于 2009-07-02 08:26 |只看该作者

回复 #1 tancotq 的帖子

你这个很正常啊,打出8,7,6来是对的!这里主要就是说明了一个问题,几乎所有的编译器的对函数参数的压栈顺序都是从右到左的而已,没有什么奇怪的现象!不知道楼主哪里不明白!
而且release和debug的主要区别是:debug是没有经过优化的,release是经过优化的。
这就导致的变量的值是从寄存器中取还是内存中取。没有优化时是从内存中取的,因此就是8,7,6,优化后的值是从寄存器中取的,因此就是
6,6,6.

[ 本帖最后由 liujunwei1234 于 2009-7-2 08:36 编辑 ]

论坛徽章:
5
5 [报告]
发表于 2009-07-02 09:05 |只看该作者
这种问题很无聊

论坛徽章:
1
双鱼座
日期:2014-08-25 19:13:11
6 [报告]
发表于 2009-07-02 09:42 |只看该作者

回复 #1 tancotq 的帖子

c 学的不到家,看看 《c陷阱于缺陷》

论坛徽章:
0
7 [报告]
发表于 2009-07-02 12:02 |只看该作者

回复 #1 tancotq 的帖子

像这种代码
        j = i++;
        k = ++i;
不同的编译器有些差别的

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
8 [报告]
发表于 2009-07-02 12:41 |只看该作者
原帖由 fleurly 于 2009-7-2 12:02 发表
像这种代码
        j = i++;
        k = ++i;
不同的编译器有些差别的

瞎说。真正有问题的是 i = ++i; or i = i++; 这种写法。

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:57:09
9 [报告]
发表于 2009-07-02 16:01 |只看该作者

回复 #7 fleurly 的帖子

真不知道你在说什么?明显和人家问的问题没关系,人家现在的这个问题绝对可不是i++或是++i的问题

论坛徽章:
0
10 [报告]
发表于 2009-07-02 18:17 |只看该作者
原帖由 liujunwei1234 于 2009-7-2 08:26 发表
你这个很正常啊,打出8,7,6来是对的!这里主要就是说明了一个问题,几乎所有的编译器的对函数参数的压栈顺序都是从右到左的而已,没有什么奇怪的现象!不知道楼主哪里不明白!
而且release和debug的主要区别是 ...



说的好~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP