为什么 C 函数会自动改变数组?
Why do C Functions Alter Arrays Automatically?
我正在学习 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 参数保持不变的原因?跟指针有关系吗?
C 在函数参数传递中使用按值传递,因此对于 non-array 类型变量,不能从被调用函数修改值。在被调用函数内部,它接收到正在传递的实际参数的副本,因此对被调用函数参数所做的任何更改都不会反映到调用方参数。
但是,在将数组传递给函数时,它会衰减到指向数组第一个元素的指针,并且该指针指向的内容可以从修改被调用的函数。这就是为什么在您的情况下,对 array[0]
的更改会反映回调用者,但对 array
本身的任何尝试更改都不会持久存在,因为 array
本身是按值传递的.
数组在传递给函数时会退化为指针。你改变的不是数组,而是数组的内容。
这两个函数是等价的:
int foo(int arr[]);
int bar(int *arr);
非官方C-FAQ有更多关于数组和指针有何不同的信息and/or类似:http://c-faq.com/aryptr/
有很多细微差别。
代替这个函数
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 );
因此,数组被用作参数,相应地作为参数,它的元素可以被改变,因为元素通过引用传递给函数。如果您将通过引用传递单个对象,如上面第一个代码片段示例所示,那么它也会被更改。
因此函数是通过引用还是通过值接受参数之间存在差异。在使用数组的情况下,它们的元素实际上通过引用传递给函数,因此可以在函数中更改。
我正在学习 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 参数保持不变的原因?跟指针有关系吗?
C 在函数参数传递中使用按值传递,因此对于 non-array 类型变量,不能从被调用函数修改值。在被调用函数内部,它接收到正在传递的实际参数的副本,因此对被调用函数参数所做的任何更改都不会反映到调用方参数。
但是,在将数组传递给函数时,它会衰减到指向数组第一个元素的指针,并且该指针指向的内容可以从修改被调用的函数。这就是为什么在您的情况下,对 array[0]
的更改会反映回调用者,但对 array
本身的任何尝试更改都不会持久存在,因为 array
本身是按值传递的.
数组在传递给函数时会退化为指针。你改变的不是数组,而是数组的内容。
这两个函数是等价的:
int foo(int arr[]);
int bar(int *arr);
非官方C-FAQ有更多关于数组和指针有何不同的信息and/or类似:http://c-faq.com/aryptr/
有很多细微差别。
代替这个函数
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 );
因此,数组被用作参数,相应地作为参数,它的元素可以被改变,因为元素通过引用传递给函数。如果您将通过引用传递单个对象,如上面第一个代码片段示例所示,那么它也会被更改。
因此函数是通过引用还是通过值接受参数之间存在差异。在使用数组的情况下,它们的元素实际上通过引用传递给函数,因此可以在函数中更改。