将数组和数组指针传递给C中的函数之间的区别

Kau*_*kar 104 c arrays function parameter-passing space-efficiency

C中两个函数有什么区别?

void f1(double a[]) {
   //...
}

void f2(double *a) {
   //...
}
Run Code Online (Sandbox Code Playgroud)

如果我要在一个相当长的数组上调用这些函数,这两个函数的行为会不同,它们会占用更多的空间吗?

Joh*_*ode 110

首先,一些标准:

6.7.5.3函数声明符(包括原型)
...
7参数声明为'' 类型数组''应调整为''限定指向 类型 '',其中类型限定符(如果有)是指定的那些内的[]所述阵列型推导.如果关键字static也出现在数组类型派生的[]中,那么对于每次对函数的调用,相应的实际参数的值应该提供对数组的第一个元素的访问,其中至少有与该大小指定的元素一样多的元素.表达.

因此,简而言之,任何函数参数声明T a[]T a[N]进行处理,就好像它被宣布T *a.

那么,为什么数组参数被视为声明为指针?原因如下:

6.3.2.1左值,数组和功能指示器
...
3除了当它是的操作数sizeof操作者或一元&运算符,或者是用于初始化数组文本的字符串,其具有输入""的阵列的表达类型 ' '被转换成类型的表达式'’指针键入指向阵列对象的初始元素,不是左值'’.如果数组对象具有寄存器存储类,则行为未定义.

给出以下代码:

int main(void)
{
  int arr[10];
  foo(arr);
  ...
}
Run Code Online (Sandbox Code Playgroud)

在调用中foo,数组表达式arr不是任何一个sizeof或的操作数&,因此根据6.2.3.1/3 ,它的类型从"10元素数组int" 隐式转换为"指向int".因此,foo将接收指针值,而不是数组值.

因为6.7.5.3/7,你可以写foo

void foo(int a[]) // or int a[10]
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

但它将被解释为

void foo(int *a)
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

因此,这两种形式是相同的.

6.99.5.3/7中的最后一句是用C99引入的,基本上意味着如果你有一个参数声明

void foo(int a[static 10])
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

对应的实际参数a必须是一个至少包含 10个元素的数组.


Tho*_*nin 28

差异纯粹是语法上的.在C中,当数组表示法用于函数参数时,它会自动转换为指针声明.

  • @Kaushik:尽管在这种情况下它们是相同的,但请记住它们在一般情况下并不相同(http://stackoverflow.com/questions/2096448/do-these-statements-about-pointers-具有相同的效果) (2认同)