2011-04-06 89 views

回答

96

首先,一些standardese

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&的操作数,因此其类型隐含地从“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个要素。

+1

使用(至少一些较旧的)MSVC C++编译器时,由于编译器错误地在两种情况下错误地修改了函数名称(在确认它们是相同的情况下),导致链接问题,这是有区别的。请参阅“不会修复”错误报告http://connect.microsoft.com/VisualStudio/feedback/details/326874/inconsistent-name-mangling-for-functions-accepting-array-and-pointer-parameters – greggo 2013-12-12 17:02:55

27

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

+1

@Kaushik:虽然他们在这种情况下是相同的,请记住,他们是不一样的[在一般情况下](http://stackoverflow.com/questions/2096448/do-these-statements-about - 指针具有相同的效果) – 2011-04-06 21:55:58

+0

@BlueRaja:是的,它是C的缺陷之一。函数参数的声明与局部变量的声明非常相似,但是存在一些细微的差别(比如作为这种数组到指针的自动变换),它们容易咬伤不知情的程序员。 – 2011-04-07 12:07:13

-2

不,他们之间没有区别。为了测试我在开发C写本C++编写代码(MinGW的)编译:

#include <stdio.h> 

void function(int* array) { 
    int a =5; 
} 

void main() { 
    int array[]={2,4}; 
    function(array); 
    getch(); 
} 

当我以.exe在IDA的二进制文件的两个调用版本的拆卸主要功能我得到酷似下同汇编代码:

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 

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

+15

对不起,但这只能证明某些版本的gcc在x86上为这两者生成了相同的程序集。正确的答案,错误的解释。 – lambdapower 2012-10-01 22:16:06