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

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

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

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

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



子衿沉夜
浏览 774回答 3
3回答

繁花如伊

首先,有些标准:6.7.5.3函数声明器(包括原型)...7参数的声明为“数组。类型“应调整为”限定指针到类型‘,其中类型限定符(如果有的话)是在[和]数组类型派生。如果关键字static也出现在[和]对于数组类型派生,然后对于函数的每次调用,对应的实际参数的值应该提供对数组的第一个元素的访问,其元素至少与大小表达式指定的元素相同。因此,简而言之,任何函数参数声明为T a[]或T a[N]被处理好像它被宣布T *a.那么,为什么数组参数被视为被声明为指针呢?原因如下:6.3.2.1值、数组和函数指示符...3除非是sizeof操作员或一元&运算符,或者是用于初始化数组的字符串文字,该表达式的类型为类型“被转换为具有类型‘指针的表达式。类型“指向数组对象的初始元素,而不是lvalue。如果数组对象具有寄存器存储类,则行为未定义。鉴于以下代码:int main(void){   int arr[10];   foo(arr);   ...}在呼唤foo,数组表达式arr都不是一个操作数sizeof或&,因此它的类型是从“10元素数组”隐式转换的。int“指向”指针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个要素。

动漫人物

这种区别纯粹是句法上的区别。在C中,当函数参数使用数组表示法时,它会自动转换为指针声明。

守着一只汪

不,他们之间没有区别。为了进行测试,我在Dev C+(明火)编译器中编写了这个C代码:#include&nbsp;<stdio.h>void&nbsp;function(int*&nbsp;array)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;a&nbsp;=5;}void&nbsp;main()&nbsp;{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;array[]={2,4}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(array); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getch();}当我拆开主函数在IDA中调用二进制文件的两个版本的.exe中得到完全相同的汇编代码,如下所示:push&nbsp;&nbsp;&nbsp;&nbsp;ebp mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ebp,&nbsp;esp sub&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;esp,&nbsp;18hand&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;esp,&nbsp;0FFFFFFF0hmov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,&nbsp;0add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,&nbsp;0Fhadd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,&nbsp;0Fhshr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,&nbsp;4shl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,&nbsp;4mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ebp+var_C],&nbsp;eax mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,&nbsp;[ebp+var_C]call&nbsp;&nbsp;&nbsp;&nbsp;sub_401730 call&nbsp;&nbsp;&nbsp;&nbsp;sub_4013D0 mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ebp+var_8],&nbsp;2mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ebp+var_4],&nbsp;4lea&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,&nbsp;[ebp+var_8]mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[esp+18h+var_18],&nbsp;eax call&nbsp;&nbsp;&nbsp;&nbsp;sub_401290 call&nbsp;&nbsp;&nbsp;&nbsp;_getch leave retn因此,这个调用的两个版本没有区别,至少编译器对它们的威胁是相等的。
打开App,查看更多内容
随时随地看视频慕课网APP