我很清楚,修改一个由值传递的函数参数在C / C ++函数之外是无效的,但是编译器允许它 - 但会发生什么?本地副本是由参数构成的,并且函数中的是可修改的吗?
#include <stdio.h>
void doSomething( int x )
{
x = 42;
printf( "The answer to Life, the Universe and Everything is (always): %i!\n", x );
}
int main( int argc, char **argv )
{
int a = 0;
doSomething( a );
return -a;
}
现在这总是在没有错误的情况下退出,但是在事物的方案(内存空间)中,函数中表示的值是x
吗?
我想这应该(合并声明和定义)开始:
void doSomething( const int x )
我会用任何一个不太合适的编译器拍我的手腕。
答案 0 :(得分:3)
对于函数doSomething()
,x
是函数的本地函数。它具有与函数体开头定义的任何其他变量类似的范围。
一般而言,x
仅存在于doSomething()
函数的范围内。一旦控件返回,x
被调用(并且参数被传递)并且被销毁,就会定义doSomething()
。只要正在执行函数调用(即变量保持在范围内),参数就与任何其他变量相同,只能通过函数调用中提供的参数进行初始化。
引用C11
,章节§6.2.1,标识符范围
[...]如果是声明符或类型说明符 声明标识符出现在块内或参数声明列表中 一个函数定义,标识符有块作用域,它终止于 相关块。 [...]
如您所知,x
是传递给函数调用的实际参数的本地副本,对函数内x
所做的任何更改都不会将反映到调用者(实际参数)中,但只要函数内x
上的操作有效,编译器就没有理由抱怨。
答案 1 :(得分:0)
函数的value参数实际上是函数的局部变量,除了它在函数调用中初始化。所以这些:
void f( int n ) {
n++;
}
和
void g() {
int n = 0;
n++;
}
如果对f()的调用是f(0),则实际上是相同的。在这两种情况下,变量都将在函数退出时被丢弃。
答案 2 :(得分:0)
形式参数x
是内存中与实际参数a
不同的单独对象,因此对x
的任何更改都不会反映在a
中。
答案 3 :(得分:0)
正如其他人所解释的那样,x
在函数doSomething
中是本地的,任何修改只会影响参数的本地副本。
但请注意,C ++允许通过引用传递:doSomething()
定义中的一个非常小的更改将对此程序产生重大影响:
void doSomething( int& x ) {
x = 42;
printf( "The answer to Life, the Universe and Everything is (always): %i!\n", x );
}
使用上述函数定义,a
中的变量main
的值确实会更改为42
。由于main()
中的代码是相同的,因此这个C ++特性会导致代码混乱,特别是对于C程序员而言。
答案 4 :(得分:-1)
值x是本地的,并保存在堆栈中。每个函数都有自己的堆栈部分,当程序进入函数时保留。 值x将位于堆栈的这一部分。它仅在定义它的函数范围内有效。 如果更改x,则仅对定义它的函数进行更改。 如果函数结束(从函数返回),为函数保留的堆栈将被销毁,因此值x也被破坏。所以x将无法访问,因为它不再存在。