3 回答
TA贡献1719条经验 获得超6个赞
首先,一些标准:
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 ,它的类型从“10元素数组int
” 隐式转换为“指向int
”。因此,foo
将接收指针值,而不是数组值。
因为6.7.5.3/7,你可以写foo
为
void foo(int a[]) // or int a[10]{ ...}
但它将被解释为
void foo(int *a){ ...}
因此,这两种形式是相同的。
6.99.5.3/7中的最后一句是用C99引入的,基本上意味着如果你有一个参数声明
void foo(int a[static 10]){ ...}
对应的实际参数a
必须是一个至少包含 10个元素的数组。
TA贡献2080条经验 获得超4个赞
不,他们之间没有区别。为了测试我在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
所以这个调用的两个版本没有区别,至少编译器会同等地威胁它们。
- 3 回答
- 0 关注
- 376 浏览
添加回答
举报