| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2144 人关注过本帖
标题:求解答一个关于 C的圆括号作用小问题
只看楼主 加入收藏
hoodlum1980
Rank: 2
来 自:浙江大学
等 级:论坛游民
威 望:2
帖 子:289
专家分:23
注 册:2008-2-24
收藏
得分:0 
回复 1# 清水河鱼 的帖子
这样的题其实挺难的,涉及到编译过程的编译器处理方式,在实际应用中我想任何程序员估计都不会故意写出这种代码。

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

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

所以答案可能是A。
2008-09-01 18:07
hoodlum1980
Rank: 2
来 自:浙江大学
等 级:论坛游民
威 望:2
帖 子:289
专家分:23
注 册:2008-2-24
收藏
得分:0 
[bo][un]清水河鱼[/un] 在 2008-8-30 12:15 的发言:[/bo]

自己都晕了,今天用tc2.0也是了一下程序,结果是11,10 ;而vc6.0 是10,10.。。。。。。


这涉及到y++这种语句参数入栈时候的编译器处理方式,我有过对这种编译器的处理分析:可以参考我博客上的这篇文章:

http://
---------------------------------------
  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-09-01 19:09
hoodlum1980
Rank: 2
来 自:浙江大学
等 级:论坛游民
威 望:2
帖 子:289
专家分:23
注 册:2008-2-24
收藏
得分:0 
以下是我刚才反汇编分析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;
}


IDA_SNAP01.jpg (106.17 KB)
图片附件: 游客没有浏览图片的权限,请 登录注册
2008-09-01 19:12
hoodlum1980
Rank: 2
来 自:浙江大学
等 级:论坛游民
威 望:2
帖 子:289
专家分:23
注 册:2008-2-24
收藏
得分:0 
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


[[it] 本帖最后由 hoodlum1980 于 2008-9-1 19:21 编辑 [/it]]
2008-09-01 19:16
StarWing83
Rank: 8Rank: 8
来 自:仙女座大星云
等 级:贵宾
威 望:19
帖 子:3951
专家分:748
注 册:2007-11-16
收藏
得分:0 
[bo][un]hoodlum1980[/un] 在 2008-9-1 18:07 的发言:[/bo]

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

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


既然不会写,那么为什么要考?
这种题目,考在编译原理里面,还稍微有点儿用处,放在C语言里面,那直接是狗屎一堆(请原谅我,实在是忍不住了)

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

专心编程………
飞燕算法初级群:3996098
我的Blog
2008-09-01 22:29
快速回复:求解答一个关于 C的圆括号作用小问题
数据加载中...
 
   



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

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