为什么C函数会自动改变数组?

时间:2017-01-30 11:19:33

标签: c arrays parameter-passing function-call

我正在学习C,我只是好奇为什么C函数,当给出像int,char,double等参数时,在调用时不改变那些参数的值,但是当它们传递给数组时参数,它们确实改变了数组元素。

例如:

void conversion(int array[])
{
    array[0] = 0;
}

void numeric(int m)
{
    m = 0;
}

当您声明并初始化int array[1] = {1}int m = 1时,使用这些参数调用函数,array[0]会更改,但int m不会。是否有更改数组参数的原因,但int参数保持不变?它与指针有关吗?

3 个答案:

答案 0 :(得分:3)

C使用pass by值进行函数参数传递,因此对于非数组类型变量,不能从被调用函数修改值。在被调用函数内部,它接收传递的实际参数的副本,因此对被调用函数参数所做的任何更改都不会反映到调用者参数。

但是,在将数组传递给函数时,它会衰减到指向数组第一个元素的指针,并且可以从被调用函数修改该指针指向的内容。这就是为什么,在您的情况下,array[0]的更改会反映给调用方,但任何尝试更改array本身都不会持续存在,因为array本身已通过按价值。

答案 1 :(得分:3)

取代此功能

void numeric(int m)
{
    m = 0;
}

请考虑以下代码段

void numeric(int *m_ptr)
{
    *m_ptr = 0;
}

//...

int m = 1;

numeric( &m );

如您所见,变量m将在函数中更改。

现在让我们使用与数组相同的函数

int m[1] = 1;

numeric( &m[0] );

在这种情况下,对象m[0]将在函数中更改。

现在这个功能

void numeric(int *m_ptr)
{
    *m_ptr = 0;
}

可以像

一样重写
void numeric(int m_ptr[])
{
    *m_ptr = 0;
}

因为声明为具有数组类型的参数被调整为指针。例如,这些函数声明

void numeric(int m_ptr[1]);
void numeric(int m_ptr[10]);
void numeric(int m_ptr[100]);
void numeric(int m_ptr[]);

彼此等效,反过来等同于函数声明

void numeric(int *m_ptr);

并声明相同的一个函数。您可以在一个编译单元中包含所有这些声明。

另一方面,传递给函数的数组被隐式转换为指向其第一个元素的指针。所以上面函数的调用

numeric( &m[0] );

相当于通话

numeric( m );

因此,数组用作参数,相应地作为参数,其元素可以更改,因为元素通过引用传递给函数。如果您将通过引用传递单个对象,如上面第一个代码段示例中所示,那么它也将被更改。

因此,函数是通过引用还是通过值接受参数之间存在差异。如果使用数组,那么它们的元素实际上是通过引用传递给函数的,因此可以在函数中进行更改。

答案 2 :(得分:1)

当传递给函数时,数组会衰减为指针。您不要更改数组,而是更改数组的内容。

这两个功能是等效的:

int foo(int arr[]);

int bar(int *arr);

非官方的C-FAQ提供了有关数组和指针如何不同和/或类似的更多信息:http://c-faq.com/aryptr/

有许多微妙的差异。