为什么这个代码 returns 0 & 1?
Why this code returns 0 & 1?
我知道后缀运算符在使用变量后增加值。
但在这种情况下,这是一个有效的陈述吗?因为看起来我正在修改它的 return 语句后的变量。
#include <iostream>
using namespace std;
int val = 0;
int foo()
{
return val++;
}
int main()
{
cout<<foo();
cout<<endl<<val;
}
任何详细说明都会有所帮助。
是的,有效。
不要认为它是返回 val
然后递增它。
相反,您将返回操作的结果 val++
。
好的,val
是一个全局变量,您可能会注意到。
当您调用 foo()
,
int foo()
{
return val++;
}
会先returnval
,也就是0
,然后递增val
,因此 val = 1
.
正如 Zenith 所引用的那样,
The expression val++
increments the value of val
, but evaluates to the value of val
before incrementing.
现在,当你 cout
val 时,val
显然是 1,因此输出是合理的。
说 return val++
首先 returns val
然后递增它是 不完全正确的 。表达式 val++
增加 val
的值,但 计算 为 val
的旧值。
您可以将后缀 ++
视为使用辅助变量保存旧值的函数:
int temp = val; // save old value to temp
++val; // increment actual value
return temp; // evaluate to old value
为了查看编译器为表示您的代码所采取的确切步骤,我检查了反汇编。
第 00324C2E 行将全局变量 "val" 的值复制到 CPU 的 eax 寄存器中。
第 00324C33 行将值从 eax 复制到 "foo" 函数的本地堆栈 space。
第 00324C39 行将全局变量 "val" 的值复制到 CPU 的 ecx 寄存器中。
00324C3F 行将 ecx 寄存器中的值加一。
第 00324C42 行将增量值从 ecx 寄存器复制回您的全局变量 "var"。
00324C48 行将存储在 "foo" 函数的本地堆栈 space 中的值的未受影响副本复制到 CPU 的 eax 中(参见上面的 00324C33 行)登记。它被复制到 eax 寄存器,因为它是返回给调用函数的值(在本例中为 "main")。
因此,从 foo() 返回 0,但全局变量 "val" 在 foo() 返回后包含 1。
int foo()
{
00324C10 push ebp
00324C11 mov ebp,esp
00324C13 sub esp,0C4h
00324C19 push ebx
00324C1A push esi
00324C1B push edi
00324C1C lea edi,[ebp-0C4h]
00324C22 mov ecx,31h
00324C27 mov eax,0CCCCCCCCh
00324C2C rep stos dword ptr es:[edi]
return val++;
00324C2E mov eax,dword ptr ds:[0032F320h]
00324C33 mov dword ptr [ebp-0C4h],eax
00324C39 mov ecx,dword ptr ds:[32F320h]
00324C3F add ecx,1
00324C42 mov dword ptr ds:[32F320h],ecx
00324C48 mov eax,dword ptr [ebp-0C4h]
}
我知道后缀运算符在使用变量后增加值。 但在这种情况下,这是一个有效的陈述吗?因为看起来我正在修改它的 return 语句后的变量。
#include <iostream>
using namespace std;
int val = 0;
int foo()
{
return val++;
}
int main()
{
cout<<foo();
cout<<endl<<val;
}
任何详细说明都会有所帮助。
是的,有效。
不要认为它是返回 val
然后递增它。
相反,您将返回操作的结果 val++
。
好的,val
是一个全局变量,您可能会注意到。
当您调用 foo()
,
int foo()
{
return val++;
}
会先returnval
,也就是0
,然后递增val
,因此 val = 1
.
正如 Zenith 所引用的那样,
The expression
val++
increments the value ofval
, but evaluates to the value ofval
before incrementing.
现在,当你 cout
val 时,val
显然是 1,因此输出是合理的。
说 return val++
首先 returns val
然后递增它是 不完全正确的 。表达式 val++
增加 val
的值,但 计算 为 val
的旧值。
您可以将后缀 ++
视为使用辅助变量保存旧值的函数:
int temp = val; // save old value to temp
++val; // increment actual value
return temp; // evaluate to old value
为了查看编译器为表示您的代码所采取的确切步骤,我检查了反汇编。
第 00324C2E 行将全局变量 "val" 的值复制到 CPU 的 eax 寄存器中。
第 00324C33 行将值从 eax 复制到 "foo" 函数的本地堆栈 space。
第 00324C39 行将全局变量 "val" 的值复制到 CPU 的 ecx 寄存器中。
00324C3F 行将 ecx 寄存器中的值加一。
第 00324C42 行将增量值从 ecx 寄存器复制回您的全局变量 "var"。
00324C48 行将存储在 "foo" 函数的本地堆栈 space 中的值的未受影响副本复制到 CPU 的 eax 中(参见上面的 00324C33 行)登记。它被复制到 eax 寄存器,因为它是返回给调用函数的值(在本例中为 "main")。
因此,从 foo() 返回 0,但全局变量 "val" 在 foo() 返回后包含 1。
int foo()
{
00324C10 push ebp
00324C11 mov ebp,esp
00324C13 sub esp,0C4h
00324C19 push ebx
00324C1A push esi
00324C1B push edi
00324C1C lea edi,[ebp-0C4h]
00324C22 mov ecx,31h
00324C27 mov eax,0CCCCCCCCh
00324C2C rep stos dword ptr es:[edi]
return val++;
00324C2E mov eax,dword ptr ds:[0032F320h]
00324C33 mov dword ptr [ebp-0C4h],eax
00324C39 mov ecx,dword ptr ds:[32F320h]
00324C3F add ecx,1
00324C42 mov dword ptr ds:[32F320h],ecx
00324C48 mov eax,dword ptr [ebp-0C4h]
}