前天实训听见几位推免的大佬聊面试中出现了动态数组,而咱们所学并无涉及到动态数组,遂翻起了尘封已久的《C语言程序设计现代方法》以及《C Primer Plus》,果真大神们写书都很全面(厚),后悔当初没有认真拜读。程序员
下面程序用到了变长数组面试
#include<stdio.h>数组
int main()
{
int i,n;安全
printf(“How many numbers do you want to reverse?”);
scanf(“%d”,&n);函数
int a[n]; //只有C99支持n决定数组范围spa
printf(“Enter %d numbers: “,n);
for(i=0;i<n;i++)
{
scanf(“%d”,&a[i]);
}
printf(“In reverse order:”); //倒序输出数组
for(i=n-1;i>=0;i–)
printf(” %d”,a[i]);
printf(“\n”);设计
return 0;指针
}内存
上面程序中的数组a是一个变长数组(variable-length array,简称VLA)。变长数组的长度是在程序执行时计算的,而不是在程序编译时计算的。变长数组的主要优势是程序员没必要在构造数组时随便给定一个长度,程序在执行时能够准确地计算出所需的元素个数。若是让程序员来制定长度,数组可能过(浪费)或太短(致使程序出错)。原型
变长数组的长度不必定要用变量来指定,任意表达式(能够含运算符)均可以,例如:
int a[3*i+5];
int b[j+k];
如今咱们已经知道什么是变长数组了,可是,假如,变长数组做为形式参数,到底应该如何写呢?
如今,假设有一函数
int sum_array( int a[n] , int n )
{
……
}
编译器会在遇到int a[n]时显示出错信息,由于此前它没有见过n。
下面给出正确的函数原型:
int sum_array(int n , int a[n] ); //version 1
int sum_array(int n , int a[*] ); //version 2
通常来讲,变长数组形式参数的长度能够是任意表达式。例如,假设咱们要编写一个函数来链接两个数组a和b,要求先复制a的元素,再复制b的元素,把结果写入第三个数组c:
int concatenate(int m , int n , int a[m] , int b[n] , int c[m+n] )
{
…
}
数组c的长度是a和b的长度之和。这里用于指定数组c长度的表达式只用到了另外两个参数;但通常来讲,该表达式可使用函数外部的变量,甚至能够调用其余函数。
敲黑板!!!重点来了
变长数组的大小不会变化,变长数组中的“变”并不表示在建立数组后还能够修改它的大小。变长数组的大小在建立后就是保持不变的。“变”的意思是说其维大小能够用变量来指定。
变长数组容许动态分配存储单元,这表示能够在程序运行时指定数组的大小。常规的C数组是静态存储分配的,也就是说在编译时数组的大小就已经肯定。
接下来要说的动态数组,才是大小会变化的数组。
如今咱们讨论C语言中如何实现动态数组。请系好安全带,加速了加速了。
基本思路就是使用malloc()库函数(内存分配)来获得一个指向一大块内存的指针。而后,像引用数组同样引用这块内存,其机理就是一个数组下标访问能够改写为一个指针加上偏移量。
1.使用malloc函数为数组分配存储空间
假设正在编写的程序须要n个整数构成的数组,这里的n能够在程序执行期间计算出来。首先,声明一个指针变量:
int *a;
一旦n的值已知了,就让程序调用malloc函数为数组分配存储空间:
a=malloc( n * sizeof(int) );
一旦a指向动态分配的内存块,就能够忽略a是指针的事实,能够把它做为数组的名字。这都要感谢C语言中数组和指针的紧密关系。例如,可使用下列循环对a指向的数组进行初始化:
for ( i=0 ; i<n ; i++ )
a[i]=0;
固然,用指针算数运算取代下标操做来访问数组元素也是可行的。
2.使用calloc函数为数组分配存储空间
calloc函数在<stdlib.h>中具备以下所示的原型:
void * calloc ( size_t nmemb , size_t size );
calloc函数为nmemb个元素的数组分配内存空间,其中每一个元素的长度都是size个字节。若是要求的空间无效,那么此函数返回空指针。在分配了内存以后,calloc函数会经过把全部位设置为0的方式进行初始化。例以下列calloc函数调用为n个整数的数组分配存储空间,而且保证全部整数初始均为零:
a=calloc(n,sizeof(int));
3.使用realloc函数调整数组的大小
一旦为数组分配完内存,稍后可能会发现数组过大或太小。realloc函数能够调整数组的大小使它更适合须要。<stdlib.h>中的realloc原型:
void * realloc ( void *ptr, size_t size );
当调用realloc函数时,ptr必须指向先前经过malloc、calloc或realloc的调用得到的内存块。size表示内存块的新尺寸,新尺寸可能会小于或大于原有尺寸。虽然realloc不要求ptr指向正在用做数组的内存,但实际上一般是这样的。
在要求减小内存块大小时,realloc函数应该“在原先的内存块上”直接进行缩减,而不须要移动存储在内存块中的数据。同理,扩大内存块时也不该该对其进行移动。若是没法扩大内存块(由于内存块后面的字节已经用于其余目的),realloc函数会在别处分配新的内存块,而后把旧块中的内容复制到新块中。因此,一旦realloc函数返回,必定要对指向内存块的全部指针进行更新,由于realloc函数可能会使内存块移动到了其余地方。