C中将数组和数组指针传递给函数的区别 [英] Difference between passing array and array pointer into function in C

查看:32
本文介绍了C中将数组和数组指针传递给函数的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

解决方案

首先,一些标准语:

<块引用>6.7.5.3 函数声明符(包括原型)
...
7 参数声明为类型的数组"应调整为限定的指向type'',其中类型限定符(如果有)是在 [] 中指定的那些数组类型推导.如果关键字 static 也出现在 []数组类型推导,然后对于函数的每次调用,对应的值实际参数应提供对数组的第一个元素的访问由大小表达式指定的元素.

所以,简而言之,任何声明为 T a[]T a[N] 的函数参数都被当作对待声明 T *a.

那么,为什么将数组参数视为声明为指针?原因如下:

<块引用>6.3.2.1 左值、数组和函数指示符
...
3 除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是一个用于初始化数组的字符串文字,类型为type"的数组的表达式是转换为类型为pointer to type"的表达式,该表达式指向的初始元素数组对象,而不是左值.如果数组对象有寄存器存储类,则行为未定义.

给定以下代码:

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[])//或 int a[10]{...}

但它会被解释为

void foo(int *a){...}

因此,这两种形式是相同的.

6.7.5.3/7的最后一句是C99引入的,基本意思就是如果你有这样的参数声明

void foo(int a[static 10]){...}

a对应的实参必须是至少10个元素的数组.

What is the difference between the two functions in C?

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

void f2(double *a) {
   //...
}

If I were to call the functions on a substantially long array, would these two functions behave differently, would they take more space on the stack?

解决方案

First, some standardese:

6.7.5.3 Function declarators (including prototypes)
...
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

So, in short, any function parameter declared as T a[] or T a[N] is treated as though it were declared T *a.

So, why are array parameters treated as though they were declared as pointers? Here's why:

6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

Given the following code:

int main(void)
{
  int arr[10];
  foo(arr);
  ...
}

In the call to foo, the array expression arr isn't an operand of either sizeof or &, so its type is implicitly converted from "10-element array of int" to "pointer to int" according to 6.2.3.1/3. Thus, foo will receive a pointer value, rather than an array value.

Because of 6.7.5.3/7, you can write foo as

void foo(int a[]) // or int a[10]
{
  ...
}

but it will be interpreted as

void foo(int *a)
{
  ...
}

Thus, the two forms are identical.

The last sentence in 6.7.5.3/7 was introduced with C99, and basically means that if you have a parameter declaration like

void foo(int a[static 10])
{
  ...
}

the actual parameter corresponding to a must be an array with at least 10 elements.

这篇关于C中将数组和数组指针传递给函数的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆