通过本地修改的值传递的参数会发生什么?

时间:2017-02-27 18:13:22

标签: c++ c parameters arguments parameter-passing

我很清楚,修改一个由值传递的函数参数在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 )

我会用任何一个不太合适的编译器拍我的手腕。

5 个答案:

答案 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将无法访问,因为它不再存在。