下面的代码(可用作控制台应用程序):
static void Main(string[] args)
{
int i = 0;
i += i++;
Console.WriteLine(i);
Console.ReadLine();
}
i的结果是0。我以为会有2个(和我的一些同事一样)。可能编译器创建了某种结构,导致i为零。
我期望2的原因是,在我的思路中,右边的语句会先求值,使I加1。然后加上i,因为i已经是1了,所以是1加1。所以1 + 1 = 2。很明显,事实并非如此。
你能解释编译器做什么或者在运行时发生了什么吗?为什么结果是零?
某种免责声明:我非常清楚您不会(而且可能不应该)使用此代码。我知道我永远不会。尽管如此,我觉得了解它为什么会以这样的方式工作以及究竟发生了什么是很有趣的。
关于这一点,我一直记得一个很好的助记法:
如果++位于表达式之后,则返回之前的值。下面的代码
int a = 1;
int b = a++;
是1,因为a在被a后面的++加起来之前是1,人们称之为后缀符号。还有一种前缀表示法,情况正好相反:如果++位于前面,表达式将返回操作之后的值:
int a = 1;
int b = ++a;
这里B是2。
对于你的代码,这意味着
int i = 0;
i += (i++);
i++返回0(如上所述),因此0 + 0 = 0。
i += (++i); // Here 'i' would become two
Scott Meyers在“有效的c++编程”中描述了这两种符号之间的区别。在内部,i++ (postfix)记住i的值,并调用前缀符号(++i)并返回旧值i。这就是为什么你应该总是在for循环中使用++i(尽管我认为所有现代编译器都在for循环中将i++转换为++i)。
c#在做什么,以及困惑的“为什么”
我还期望值为1…但对这个问题的一些探索确实澄清了一些观点。
考虑以下方法:
static int SetSum(ref int a, int b) { return a += b; }
static int Inc(ref int a) { return a++; }
我期望i+ = i++与SetSum(ref I, Inc(ref I))相同。语句之后的i值是1:
int i = 0;
SetSum(ref i, Inc(ref i));
Console.WriteLine(i); // i is 1
但后来我得出了另一个结论……I += i++实际上和I = I + i++…所以我创建了另一个类似的例子,使用这些函数:
static int Sum(int a, int b) { return a + b; }
static int Set(ref int a, int b) { return a = b; }
调用这个Set(ref i, Sum(i, Inc(ref i)))后,i的值为0:
int i = 0;
Set(ref i, Sum(i, Inc(ref i)));
Console.WriteLine(i); // i is 0
这不仅解释了c#在做什么……但这也是为什么很多人对它感到困惑……包括我。