在C中传递数组和数组指针到函数中的区别

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

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

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

首先,一些标准 :

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); ... } 

在对foo的调用中,数组表达式arr不是sizeof或者&的操作数,所以它的类型根据6.2.3.1/3从“ int 10元素数组”隐式转换为“ int指针”。 因此, foo将收到一个指针值,而不是一个数组值。

因为6.7.5.3/7,你可以写成foo

 void foo(int a[]) // or int a[10] { ... } 

但它会被解释为

 void foo(int *a) { ... } 

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

6.7.5.3/7中的最后一句是用C99引入的,基本上就是说如果你有一个参数声明就好

 void foo(int a[static 10]) { ... } 

对应于a的实际参数必须是一个至少有 10个元素的数组。

区别纯粹是合成的。 在C中,当数组符号用于函数参数时,它会自动转换为指针声明。

不,他们之间没有区别。 为了测试我在Dev C ++(mingw)编译器中编写了这个C代码:

 #include <stdio.h> void function(int* array) { int a =5; } void main() { int array[]={2,4}; function(array); getch(); } 

当我在IDA中对二进制文件的两个调用版本的.exe中的主要函数进行反汇编时,我会得到完全相同的汇编代码,如下所示:

 push ebp mov ebp, esp sub esp, 18h and esp, 0FFFFFFF0h mov eax, 0 add eax, 0Fh add eax, 0Fh shr eax, 4 shl eax, 4 mov [ebp+var_C], eax mov eax, [ebp+var_C] call sub_401730 call sub_4013D0 mov [ebp+var_8], 2 mov [ebp+var_4], 4 lea eax, [ebp+var_8] mov [esp+18h+var_18], eax call sub_401290 call _getch leave retn 

所以这个调用的两个版本之间没有区别,至少编译器会威胁到它们。