在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
所以这个调用的两个版本之间没有区别,至少编译器会威胁到它们。