VC 和 C# 真的差别到家了。。。

ArLi2003 2003-09-07 07:00:56
今天我在msnews 见到一个人说 (x++)+(++x)+(x++) 在vc 和c# 中不同,我试了一下:

VC 代码如下(MFC):

#include <iostream>
using namespace std;

void main()
{
int x = 1;
int y = (x++)+(++x)+(x++);

cout << y << endl;
cin.ignore();
}

C# 代码如下:

using System;

public class myclass {

static void Main() {
int x =1;
int y = (x++)+(++x)+(x++);

System.Console.Write(y.ToString());
System.Console.Read();
}
}

二者结果居然,VC 是6 而C# 是7

由于VC 我是用MFC 写的,没法转IL,于是我将VC 的重新写成了.net 在IL 上进行了编译,

这是VC 的IL
.method public static int32 modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
main() cil managed
{
.vtentry 1 : 1
// 代码大小 36 (0x24)
.maxstack 2
.locals init ([0] int32 x,
[1] int32 y)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.1
IL_0004: add
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldloc.0
IL_0008: add
IL_0009: ldloc.0
IL_000a: add
IL_000b: stloc.1
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: add
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.1
IL_0015: call void [mscorlib]System.Console::Write(int32)
IL_001a: call int32 [mscorlib]System.Console::Read()
IL_001f: pop
IL_0020: ldc.i4.0
IL_0021: br.s IL_0023
IL_0023: ret
} // end of method 'Global Functions'::main

这是C# 的IL

.method private hidebysig static void Main() cil managed
{
.entrypoint
// 代码大小 39 (0x27)
.maxstack 4
.locals init ([0] int32 x,
[1] int32 y)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.1
IL_0009: add
IL_000a: dup
IL_000b: stloc.0
IL_000c: add
IL_000d: ldloc.0
IL_000e: dup
IL_000f: ldc.i4.1
IL_0010: add
IL_0011: stloc.0
IL_0012: add
IL_0013: stloc.1
IL_0014: ldloca.s y
IL_0016: call instance string [mscorlib]System.Int32::ToString()
IL_001b: call void [mscorlib]System.Console::Write(string)
IL_0020: call int32 [mscorlib]System.Console::Read()
IL_0025: pop
IL_0026: ret
} // end of method myclass::Main

在后面,明显多了个add,晕。。。不知有没有讨论过?
...全文
346 53 打赏 收藏 转发到动态 举报
写回复
用AI写文章
53 条回复
切换为时间正序
请发表友善的回复…
发表回复
ArLi2003 2003-09-11
  • 打赏
  • 举报
回复
算啦算啦,反正目前我没有正版,也不是MS 什么亲戚,结帐
ArLi2003 2003-09-10
  • 打赏
  • 举报
回复
已经48 小时了,算了我取消公告了,以后还是搞封装,然后传递实数算了,呵呵
i三千 2003-09-10
  • 打赏
  • 举报
回复
学习~
poseidonli 2003-09-10
  • 打赏
  • 举报
回复
我分析了一下楼主给出的IL,写了注释,发现在IL_000b的时候已经得出答案了,而在这之前只对x进行两次赋值,一次得到x=1,一次得到x=2,然后就直接得出了最终的答案!
.vtentry 1 : 1
// 代码大小 36 (0x24)
.maxstack 2
.locals init ([0] int32 x,
[1] int32 y)
IL_0000: ldc.i4.1 //将1入栈
IL_0001: stloc.0 // 将1赋给变量x,x=1
IL_0002: ldloc.0 // 将x=1压入堆栈
IL_0003: ldc.i4.1 //将1入栈
IL_0004: add //相加,栈顶为2
IL_0005: stloc.0 // 将2赋给变量x,x=2
IL_0006: ldloc.0 // 将x=2压入堆栈
IL_0007: ldloc.0 // 将x=2压入堆栈
IL_0008: add //相加,栈顶为4
IL_0009: ldloc.0 // 将x=2压入堆栈
IL_000a: add //相加,栈顶为6
IL_000b: stloc.1 // 将6赋给变量x1,x1=6
IL_000c: ldloc.0 // 将x=2压入堆栈
IL_000d: ldc.i4.1 // 将1压入堆栈
IL_000e: add //相加,栈顶为3
IL_000f: stloc.0 // 将3赋给变量x,x=3
IL_0010: ldloc.0 // 将x=2压入堆栈
IL_0011: ldc.i4.1 // 将1压入堆栈
IL_0012: add //相加,栈顶为3
IL_0013: stloc.0 // 将3赋给变量x,x=3
IL_0014: ldloc.1 // 将x=6压入堆栈
IL_0015: call void [mscorlib]System.Console::Write(int32)
IL_001a: call int32 [mscorlib]System.Console::Read()
IL_001f: pop
IL_0020: ldc.i4.0
IL_0021: br.s IL_0023
IL_0023: ret
对于c#,在得出结果以前x进行了很多次的赋值,最后得到的x为四
{ .entrypoint
// 代码大小 39 (0x27)
.maxstack 4
.locals init ([0] int32 x,
[1] int32 y)
IL_0000: ldc.i4.1 //将1入栈
IL_0001: stloc.0 // 将1赋给变量x,x=1
IL_0002: ldloc.0 // 将x=1压入堆栈
IL_0003: dup // 将x=1压入堆栈(复制)
IL_0004: ldc.i4.1 //将1入栈
IL_0005: add //相加,栈顶为2
IL_0006: stloc.0 // 将2赋给变量x,x=2
IL_0007: ldloc.0 // 将x=2压入堆栈
IL_0008: ldc.i4.1 //将1入栈
IL_0009: add //相加,栈顶为3
IL_000a: dup // 将x=3压入堆栈(复制)
IL_000b: stloc.0 // 将3赋给变量x,x=3
IL_000c: add //相加,栈顶为4
IL_000d: ldloc.0 // 将x=3压入堆栈
IL_000e: dup // 将x=3压入堆栈(复制)
IL_000f: ldc.i4.1 //将1入栈
IL_0010: add //相加,栈顶为4
IL_0011: stloc.0 // 将3赋给变量x,x=4
IL_0012: add //相加,栈顶为7
IL_0013: stloc.1 // 将7赋给变量x1,x1=7
IL_0014: ldloca.s y
IL_0016: call instance string [mscorlib]System.Int32::ToString()
IL_001b: call void [mscorlib]System.Console::Write(string)
IL_0020: call int32 [mscorlib]System.Console::Read()
IL_0025: pop
IL_0026: ret
不知道为什么vc++好像对(x++)或者(++x)之类的语句视而不见
但是c#却符合我们用语法分析的结果
可能解释的不是很好,或者有点错误
请各位高手指教
zfbt 2003-09-10
  • 打赏
  • 举报
回复
天啊,这样也有差别啊!:(
wildhorse01 2003-09-09
  • 打赏
  • 举报
回复
bcb输出为6
dreammaster 2003-09-09
  • 打赏
  • 举报
回复
按说m$在这个问题上应该统一起来

其实就是c++

如果按 int x = 1;
int y = x++;
int z = ++x;
int p = x++;
Console::WriteLine(y + z + p);

上结果应该与C#相同,但当写在同一表达式中则运算方式有很大区别,
在C 中的main的代码如下:

int x = 1;

Console::WriteLine(x++ + ++x + x++);

直接利用vc.net做出,ildasm后的代码片段如下
IL_0000: ldc.i4.1 //将1入栈
IL_0001: stloc.0 //将栈中的值赋给第一个变量 x = 1;
IL_0002: ldloc.0 //将变量入栈
IL_0003: ldc.i4.1 //将1入栈
IL_0004: add //将刚入栈的变量与1相加并推入栈中 栈最上面的值为2
IL_0005: stloc.0 //将栈中的值赋给第一个变量 x = 2;
IL_0006: ldloc.0 //将变量x入栈 x=2
IL_0007: ldloc.0 //再将变量x入栈 x= 2
IL_0008: add //两个变量相加后值入栈,栈最上面的值为4
IL_0009: ldloc.0 //将变量x入栈 x=2
IL_000a: add //栈前两值相加 2+4 =6,放入栈顶.
IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0010: ldloc.0 //将x入栈 x=2
IL_0011: ldc.i4.1 //将1入栈
IL_0012: add //1+x后将值放入栈顶
IL_0013: stloc.0 //将栈顶的值赋给x x=3
IL_0014: ldloc.0 //将变量x入栈 x=3
IL_0015: ldc.i4.1 //将1入栈
IL_0016: add //1+x 相加,将结果置于栈顶
IL_0017: stloc.0 //将栈顶的值赋给x x=4
IL_0018: ldc.i4.0
IL_0019: br.s IL_001b

IL_001b: ret


上面的il分析不难看出在c++这个等式的计算中似乎先计算 ++x的值2,然后再+2(x++) +2(x++)

最后才进行x++的计算,不知道对也不对.
NEODIO 2003-09-09
  • 打赏
  • 举报
回复
ehm..............................
IL不一样.........................
yyfa6 2003-09-09
  • 打赏
  • 举报
回复
up
Kain 2003-09-09
  • 打赏
  • 举报
回复
mark
veaven 2003-09-09
  • 打赏
  • 举报
回复
up
wjhs 2003-09-09
  • 打赏
  • 举报
回复
up
hehaorome 2003-09-09
  • 打赏
  • 举报
回复
强烈关注!
CForce 2003-09-09
  • 打赏
  • 举报
回复
int x=0;
for(int i=0;i<100;i++)
x=x++;
Console.WriteLine(x);

觉得写这种代码的人,就是自己找自己麻烦。而且我觉得最多出现这种代码的地方就是咱们大学教材、试题......
ArLi2003 2003-09-08
  • 打赏
  • 举报
回复
这个(x++)+(++x)+(x++) 由于左右平等,所以不存在左先还是右先的问题

注意IL 中的差别
jackyhzzjcn 2003-09-08
  • 打赏
  • 举报
回复
这样写一个表达式是不是过了点? 呵呵
win911 2003-09-08
  • 打赏
  • 举报
回复
晕.楼上的都在说什么啊!!!!

楼主的意思是说同一个表达式vc和c#在IL中的不同!!!!
dreammaster 2003-09-08
  • 打赏
  • 举报
回复
++x,x++其方式均为将操作数加1

++x 的值为加1后的值

x++ 的值为加1前的值

如果(x++) + (++x) + (x++)存在这三组括号,则运算从左到右为

(x++) = 1,此时x=2
(++x) = 3,此时x=3
(x++) = 3,此时x=4

最后x=4,(1+3+3)=7这是C#中的处理方式,但不知道C++为何这样奇怪?
janus1999 2003-09-08
  • 打赏
  • 举报
回复
今天总算开了眼,这种东西可以在校生要多看看,说不定哪天老师就考这样的题目...
Jacode 2003-09-08
  • 打赏
  • 举报
回复
有谁清楚C++标准和C#标准的说说
加载更多回复(33)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧