淺析變長數組(VLA)和動態數組

前天實訓聽見幾位推免的大佬聊面試中出現了動態數組,而咱們所學並無涉及到動態數組,遂翻起了塵封已久的《C語言程序設計現代方法》以及《C Primer Plus》,果真大神們寫書都很全面(厚),後悔當初沒有認真拜讀。程序員

1、C99中的變長數組

下面程序用到了變長數組面試

#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數組是靜態存儲分配的,也就是說在編譯時數組的大小就已經肯定。

接下來要說的動態數組,纔是大小會變化的數組。

2、動態數組

如今咱們討論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函數可能會使內存塊移動到了其餘地方。

相關文章
相關標籤/搜索