将数组和数组指针传递给C中的函数之间的区别
Posted
技术标签:
【中文标题】将数组和数组指针传递给C中的函数之间的区别【英文标题】:Difference between passing array and array pointer into function in C 【发布时间】:2011-07-31 04:58:09 【问题描述】:C 中这两个函数有什么区别?
void f1(double a[])
//...
void f2(double *a)
//...
如果我要在一个相当长的数组上调用函数,这两个函数的行为会有所不同,它们会占用更多的堆栈空间吗?
【问题讨论】:
【参考方案1】:首先,一些standardese:
6.7.5.3 函数声明符(包括原型) ... 7 将参数声明为“type”的数组应调整为“qualified pointer to type'',其中类型限定符(如果有)是在[
和]
的 数组类型推导。如果关键字static
也出现在[
和]
的 数组类型推导,然后每次调用函数,对应的值 实际参数应提供对数组的第一个元素的访问,其中至少有 由 size 表达式指定的元素。
因此,简而言之,任何声明为T a[]
或T a[N]
的函数参数都被视为就像它被声明为T *a
。
那么,为什么数组参数被视为声明为指针?原因如下:
6.3.2.1 左值、数组和函数指示符 ... 3 除非它是sizeof
运算符或一元&
运算符的操作数,或者是 用于初始化数组的字符串字面量,类型为“array of type”的表达式是 转换为类型为“pointer to type”的表达式,它指向 数组对象并且不是左值。如果数组对象有寄存器存储类,则 行为未定义。
给定以下代码:
int main(void)
int arr[10];
foo(arr);
...
在对foo
的调用中,数组表达式arr
不是sizeof
或&
的操作数,因此其类型从“int
的10 元素数组”隐式转换为“指向int
的指针”根据 6.2.3.1/3。因此,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个元素的数组。
【讨论】:
在使用(至少一些较旧的)MSVC C++ 编译器时存在差异,因为编译器在这两种情况下错误地对函数名称进行了不同的处理(同时认识到它们在其他情况下是相同的),导致在链接问题。请参阅此处的“无法修复”错误报告connect.microsoft.com/VisualStudio/feedback/details/326874/…【参考方案2】:区别纯粹是语法上的。在 C 语言中,当函数参数使用数组表示法时,它会自动转换为指针声明。
【讨论】:
@Kaushik:虽然在这种情况下它们是相同的,但请记住它们并不相同in the general case @BlueRaja: 是的,这是C语言的缺陷之一。函数参数的声明与局部变量的声明非常相似,但有一些微妙之处容易让粗心的程序员陷入困境的差异(例如这种数组到指针的自动转换)。【参考方案3】:不,它们之间没有区别。为了测试我在 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 中反汇编 main 函数时,我得到完全相同的汇编代码,如下所示:
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
所以这个调用的两个版本没有区别,至少编译器对它们的威胁是一样的。
【讨论】:
对不起,但这仅证明某些版本的 gcc 在 x86 上为两者生成了相同的程序集。正确答案,错误解释。以上是关于将数组和数组指针传递给C中的函数之间的区别的主要内容,如果未能解决你的问题,请参考以下文章