| 编程中国 | 业界新闻 | 技术文章 | 视频教程 | 下载频道 | 程序源码 | 个人空间 | 编程论坛
全能ASP/PHP/ASP.NET主机,支持月付专业 MSSQL 数据库空间,支持月付专业 MySQL 数据库空间,支持月付学习型 ASP/PHP/ASP.NET 主机 30元/年
高端软件开发 = 年薪十万不是梦   
共有 430 人关注过本帖
标题:求解答一个关于 C的圆括号作用小问题
收藏  订阅  推荐  打印
haole1234
Rank: 1
等级:新手上路
帖子:2
积分:120
注册:2008-8-30

2楼说的没错


[url=http://www.930v.com/] [/url]

http://www.ah930.cn
2008-8-30 17:50
QQ0001000
Rank: 3Rank: 3
等级:中级会员
帖子:220
积分:2372
注册:2007-3-29

最好不在要输入,输出中包含计算表达式.这样程序才会有较强的可移植性

2008-8-30 18:25
hoodlum1980
Rank: 3Rank: 3
来自:浙江大学
等级:中级会员
帖子:248
积分:3294
注册:2008-2-24
回复 1# 清水河鱼 的帖子

这样的题其实挺难的,涉及到编译过程的编译器处理方式,在实际应用中我想任何程序员估计都不会故意写出这种代码。

括号这个题的上下文里表示的是需要打印输出()内这个表达式的值,(x++, y)的值为当前的y值。

另外一点注意的是,函数调用时,参数从右向左被入栈,所以先执行的是最右侧的参数(y++)。所以打印的第二个数是当前的y,然后y被++,这时候第一个%d相当于是(y++)执行后的y值。

所以答案可能是A。
2008-9-1 18:07
hoodlum1980
Rank: 3Rank: 3
来自:浙江大学
等级:中级会员
帖子:248
积分:3294
注册:2008-2-24

引用:
清水河鱼 在 2008-8-30 12:15 的发言:

自己都晕了,今天用tc2.0也是了一下程序,结果是11,10 ;而vc6.0 是10,10.。。。。。。
这涉及到y++这种语句参数入栈时候的编译器处理方式,我有过对这种编译器的处理分析:可以参考我博客上的这篇文章:

http://www.cnblogs.com/hoodlum1980/archive/2008/02/25/1079983.html
---------------------------------------
  int x = 11;
  int y = 10;
  printf("%d,%d",(x++ , y), y++);
---------------------------------------
翻译到TC2.0的等效代码为:(未进行反汇编分析,我的猜测)
push y;  //10入栈;
y++;     //y=11;
push y   //11入栈
x=x_1;
printf("%d, %d", 11, 10);
----------------------------------------

翻译到VC6.0下面的等效代码(使用反汇编分析的结果):
----------
前提条件:
x=11;y=10;
------------

x=x+1;
temp=y;
push temp;
push y;
y=y+1;
printf("%d,%d", y, temp);
2008-9-1 19:09
hoodlum1980
Rank: 3Rank: 3
来自:浙江大学
等级:中级会员
帖子:248
积分:3294
注册:2008-2-24

以下是我刚才反汇编分析VC6.0的反汇编截图(Main函数的主体部分,现场保护和复原等部分未能涵盖进去):在汇编代码后面已经添加了注释。

在VC6.0的源代码如下:
复制内容到剪贴板
代码:
#include "stdafx.h"
#include <stdio.h>

int main(int argc, char* argv[])
{
    int x = 11;
    int y = 10;
    printf("%d,%d",(x++ , y), y++);
    return 0;
}
附件: 只有本站会员才能下载或查看附件,请您 登录注册
2008-9-1 19:12
hoodlum1980
Rank: 3Rank: 3
来自:浙江大学
等级:中级会员
帖子:248
积分:3294
注册:2008-2-24

Main函数的反汇编代码:
复制内容到剪贴板
代码:
.text:00401010 main            proc near               ; CODE XREF: j_mainj
.text:00401010
.text:00401010 var_4C          = dword ptr -4Ch
.text:00401010 var_C           = dword ptr -0Ch
.text:00401010 var_8           = dword ptr -8
.text:00401010 var_4           = dword ptr -4
.text:00401010
.text:00401010                 push    ebp             ; 保护EBP
.text:00401011                 mov     ebp, esp        ; 把堆栈指针复制到EBP
.text:00401013                 sub     esp, 4Ch        ;
.text:00401016                 push    ebx             ; 保护EBX,ESI,EDI
.text:00401017                 push    esi
.text:00401018                 push    edi
.text:00401019                 lea     edi, [ebp+var_4C]
.text:0040101C                 mov     ecx, 13h
.text:00401021                 mov     eax, 0CCCCCCCCh
.text:00401026                 rep stosd
.text:00401028                 mov     [ebp+var_4], 0Bh ; 在栈上设置第一个临时变量x=11,地址是[sp-4]
.text:0040102F                 mov     [ebp+var_8], 0Ah ; 在栈上设置第二个临时变量y=10,地址是[sp-8]
.text:00401036                 mov     eax, [ebp+var_4] ; 下面三句:执行x=x+1;
.text:00401039                 add     eax, 1
.text:0040103C                 mov     [ebp+var_4], eax
.text:0040103F                 mov     ecx, [ebp+var_8] ; 在栈上设置第三个临时变量temp,并执行temp=y; 地址是[sp-12]
.text:00401042                 mov     [ebp+var_C], ecx
.text:00401045                 mov     edx, [ebp+var_C] ; 以下两句:push temp; 此时首个进入栈中的参数=10
.text:00401048                 push    edx
.text:00401049                 mov     eax, [ebp+var_8] ; 以下两句:push y; 此时第二个栈中的参数=10
.text:0040104C                 push    eax
.text:0040104D                 push    offset ??_C@_05BBIB@?$CFd?0?$CFd?$AA@ ; 入栈第三个参数是"%d,%d"字符串的地址
.text:00401052                 mov     ecx, [ebp+var_8] ; 以下三句:执行y=y+1; 执行后y=11;
.text:00401055                 add     ecx, 1
.text:00401058                 mov     [ebp+var_8], ecx
.text:0040105B                 call    printf          ; 调用printf函数,相当于printf("%d,%d",10,10);
.text:00401060                 add     esp, 0Ch
.text:00401063                 xor     eax, eax
.text:00401065                 pop     edi             ; 恢复EDI,ESI,EBX
.text:00401066                 pop     esi
.text:00401067                 pop     ebx
.text:00401068                 add     esp, 4Ch        ; 复原 栈指针
.text:0040106B                 cmp     ebp, esp
.text:0040106D                 call    __chkesp
.text:00401072                 mov     esp, ebp
.text:00401074                 pop     ebp
.text:00401075                 retn                    ; Main函数结束
.text:00401075 main            endp
[ 本帖最后由 hoodlum1980 于 2008-9-1 19:21 编辑 ]
2008-9-1 19:16
StarWing83
Rank: 12Rank: 12Rank: 12
来自:湖北工业大学
等级:版主
威望:9
帖子:2476
积分:26129
注册:2007-11-16

引用:
hoodlum1980 在 2008-9-1 18:07 的发言:

这样的题其实挺难的,涉及到编译过程的编译器处理方式,在实际应用中我想任何程序员估计都不会故意写出这种代码。

括号这个题的上下文里表示的是需要打印输出()内这个表达式的值,(x++, y)的值为当前的y值。 ...
既然不会写,那么为什么要考?
这种题目,考在编译原理里面,还稍微有点儿用处,放在C语言里面,那直接是狗屎一堆(请原谅我,实在是忍不住了)

KR是这么说的:“如果你不了解这种语句在你的机器上的实现,那么这种无知恰恰可以保护你!

专心编程………
飞燕算法初级群:3996098
我的Blog
2008-9-1 22:29
共有 429 人关注过本帖
关于我们 | 广告合作 | 编程中国 | 清除Cookies | Archiver | WAP | TOP

编程中国 版权所有,并保留所有权利。鲁ICP备08000592号
Powered by Discuz, Processed in 0.050062 second(s), 9 queries.
Copyright©2004-2008, BCCN.NET, All Rights Reserved