通过将数组作为参数传递给函数来增加数组的大小

时间:2017-08-27 11:03:47

标签: c arrays pointers implicit-conversion

#include<stdio.h>
void fun1(int a[100])
{
  a[4]=1;
}
void main()
{
   int a[2]={1,2};
   fun1(a);
   printf("%d",a[4]);   // Output 1
}

我知道当我们将数组作为函数参数传递时,数组会被衰减为指向第一个元素的指针。但是主要功能中阵列的大小如何增加?

2 个答案:

答案 0 :(得分:3)

根据C标准(6.7.6.3函数声明符(包括原型))

  

7应调整参数声明为''数组'的数组   to ''限定指向类型'',其中类型限定符(如果有的话)   是在数组类型的[和]内指定的那些   推导....

这意味着在声明中

void fun1(int a[100])
{
  a[4]=1;
}

将函数参数调整为int *类型,结果该函数实际上具有以下声明

void fun1( int *a )
{
  a[4]=1;
}

例如,以下函数声明

void fun1(int a[2]);
void fun1(int a[10]);
void fun1(int a[100]);

声明与声明类似的一个函数

void fun1(int *a);

另一方面,表达式中使用的数组(例如函数参数)被隐式转换为指向其第一个元素的指针。所以在这个函数中调用表达式使用数组指示符

fun1(a);

数组指示符a被转换为指向其第一个元素的指针,而参数的表达式具有类型int *

您可以通过以下方式想象此调用

{
    int *temporary p = a;
    fun1( p );
}    

因此函数参数的类型为int *,它是一个指针,相应的参数也是一个指针。该函数不处理数组类型的对象。它处理指针类型的对象。

因此,没有数组增加其大小并且原始程序具有未定义的行为,因为尝试访问原始数组之外的内存。

通过输出参数的大小,您可以轻松检查函数是否处理指针。例如

void fun1(int a[100])
{
    printf( "sizeof( a ) = %zu\n", sizeof( a ) );
    a[4]=1;
}

根据使用的系统,输出将等于48。但无论如何,它不会像你期望的那样等于100 * sizeof( int )

答案 1 :(得分:2)

cant 更改自动数组运行时的大小。

如果要在运行时选择声明的自动数组的大小,可以使用(自c99起)VLA

int n;
scanf("%d", &n)
int a[n];

或者如果您确实需要更改数组运行时的大小,则必须在堆上动态分配内存,然后在realloc缓冲区大小。

int *a = malloc(sizeof(int) * 2);
int *tmp = realloc(a, sizeof(int) * 4);
if (tmp == NULL)
{
    // Reallocation failed
}
else
{
    a = tmp;
}

正如@DavidBowling所说,最好使用解除引用的标识符而不是sizeof表达式中的类型。在我们的例子中,它将是

int *a = malloc(sizeof *a * 2);
int *tmp = realloc(a, sizeof *tmp * 4);

它更容易&amp;当指针类型发生变化时,不易出错。