1. 程式人生 > >C語言的那些小祕密之動態陣列

C語言的那些小祕密之動態陣列

摘要的重要性是不言而喻的,每次發文章我都很糾結如何寫出一個有特色的摘要來,能夠以最為簡短的文字向讀者描述出我所要表達的東西。但是常常出現的問題是,摘要寫得太簡短了,讀者看了不清楚文章究竟要講啥;摘要寫得稍微長點的話自然能夠描述清楚所要表達的東西,但是卻也出現了另外一個問題,就是讀者看到大段的文字描述,覺得枯燥無味,直接二話不說給文章判了個“死刑”,導致這種情況下願意真正的花時間看完摘要的讀者屈指可數,更不用說文章的正文部分了,所以時長感慨寫文章最頭疼的莫過於摘要了。

很多人在編寫C語言程式碼的時候很少使用動態陣列,不管什麼情況下通通使用靜態陣列的方法來解決,在當初學習C語言的時候我就是一個典型的例子,但是現在發現這是一個相當不好的習慣,甚至可能導致編寫的程式出現一些致命的錯誤。尤其對於搞嵌入式的人來所,嵌入式系統的記憶體是寶貴的,記憶體是否高效率的使用往往意味著嵌入式裝置是否高質量和高效能,所以高效的使用記憶體對我們來說是很重要的。那麼我們在自己編寫C語言程式碼的時候就應該學會使用動態陣列,這也就是我這篇部落格要給大家講的,我盡我所能的用一些簡單的程式碼來講解動態陣列,希望我所講的對你有所幫助。

那麼我們首先來看看什麼是動態陣列,動態陣列是相對於靜態陣列而言,從“動”字我們也可以看出它的靈活性,靜態陣列的長度是預先定義好的,在整個程式中,一旦給定大小後就無法改變。而動態陣列則不然,它可以隨程式需要而重新指定大小。動態陣列的記憶體空間是從堆動態分配的。是通過執行程式碼而為其分配儲存空間。當程式執行到我們編寫的分配語句時,才為其分配。對於靜態陣列,其建立非常方便,使用完也無需釋放,要引用也簡單,但是建立後無法改變其大小是其致命弱點!對於動態陣列,其建立麻煩,使用完必須由程式設計師自己釋放,否則將會引起記憶體洩露。但其使用非常靈活,能根據程式需要動態分配大小。所以相對於靜態陣列的來說我們對於使用動態陣列有很大的自由度。

在建立動態陣列的過程中我們要遵循一個原則,那就是在建立的時候從外層往裡層,逐層建立;而釋放的時候從裡層往外層,逐層釋放。這個話你讀了可能理解並不深刻,不過不要急,接下來我們看看兩段程式碼。

一維動態陣列的建立:

#include <stdio.h>
#include <stdlib.h>
int main()
{
int n1,i;
int *array;
printf("請輸入所要建立的一維動態陣列的長度:");
scanf("%d",&n1);
array=(int*)calloc(n1,sizeof(int));
for(i=0;i<n1;i++)
{
 printf("%d\t",array[i]);
}
printf("\n");
for(i=0;i<n1;i++)
{
 array[i]=i+1;
 printf("%d\t",array[i]);
}
 free(array);//釋放第一維指標
return 0;
}

執行結果為:

特此說明:在以後的執行結果部分,我均會附上文字結果,以防圖片開啟失敗。

請輸入所要建立的一維動態陣列的長度:4
0       0       0       0
1       2       3       4       Press any key to continue

在此我使用的是calloc()函式來分配的,同時也使用兩個for語句來列印陣列元素,我們發現第一個列印輸出的陣列元素值均為0,在此也是為了加深讀者對於calloc()函式的印象我特地使用了它來分配,如果對於calloc()、malloc()、realloc()函式的區別還是很清楚的讀者可以去看看我的另外一篇部落格------C語言的那些小祕密之記憶體分配。

二維陣列的建立:

#include <stdio.h>
#include <stdlib.h>
int main()
{
int n1,n2;
int **array,i,j;
printf("請輸入所要建立的動態陣列的第一維長度:");
scanf("%d",&n1);
printf("請輸入所要建立的動態陣列的第二維長度:");
scanf("%d",&n2);
array=(int**)malloc(n1*sizeof(int*)); //第一維
for(i=0;i<n1; i++)
{
array[i]=(int*)malloc(n2* sizeof(int));//第二維
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
array[i][j]=i*n2+j+1;
printf("%d\t",array[i][j]);
}
printf("\n");
}
for(i=0;i<n1;i++)
{
free(array[i]);//釋放第二維指標
}
free(array);//釋放第一維指標
return 0;
}

執行結果為:

 請輸入所要建立的動態陣列的第一維長度:3
請輸入所要建立的動態陣列的第二維長度:3
1       2       3
4       5       6
7       8       9
Press any key to continue

有了上面的程式碼我們再來說動態陣列的建立就簡單了,以二維為例,先說建立,還記得我們上面說的建立的原則嘛:從外層往裡層,逐層建立。

array=(int**)malloc(n1*sizeof(int*)); //第一維

以上是我們建立二維動態陣列的最外層,建立好了最外層那麼我們接下來就是要建立次外層了。

array[i]=(int*)malloc(n2* sizeof(int));//第二維

在建立次外層的過程中我們使用了一個for喜歡語句,千萬別忘了使用for迴圈語句,這是絕大多數人的一個易錯點。

建立好了接下來我們該講到釋放了,而釋放的時候從裡層往外層,逐層釋放。剛剛與我們上面的建立相反,在以上程式碼中我們首先使用了下面一個for迴圈來釋放裡層。

for(i=0;i<n1;i++)
{
free(array[i]);//釋放第二維指標
}

在通過以下語句來釋放外層。
free(array);//釋放第一維指標

如果出現多維的情況怎麼做呢,我們接下來再來看看一個三維動態陣列的建立和釋放,以加深下讀者的印象。程式碼如下:

#include <stdlib.h>
#include <stdio.h>
int main()
{
int n1,n2,n3;
int ***array;
int i,j,k;
printf("請輸入所要建立的動態陣列的第一維長度:");
scanf("%d",&n1);
printf("請輸入所要建立的動態陣列的第二維長度:");
scanf("%d",&n2);
printf("請輸入所要建立的動態陣列的第三維長度:");
scanf("%d",&n3);
array=(int***)malloc(n1*sizeof(int**));//第一維
for(i=0; i<n1; i++)
{
array[i]=(int**)malloc(n2*sizeof(int*)); //第二維
for(j=0;j<n2;j++)
{
array[i][j]=(int*)malloc(n3*sizeof(int)); //第三維
}
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
for(k=0;k<n3;k++)
{
array[i][j][k]=i+j+k+1;
printf("%d\t",array[i][j][k]);
}
printf("\n");
}
printf("\n");
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
free(array[i][j]);//釋放第三維指標
}
}
for(i=0;i<n1;i++)
{
free(array[i]);//釋放第二維指標
}
free(array);//釋放第一維指標
return 0;
}

執行結果為:


請輸入所要建立的動態陣列的第一維長度:3
請輸入所要建立的動態陣列的第二維長度:3
請輸入所要建立的動態陣列的第三維長度:3
1       2       3
2       3       4
3       4       5

2       3       4
3       4       5
4       5       6

3       4       5
4       5       6
5       6       7

Press any key to continue

看了以上三維動態陣列的建立和釋放程式碼以後,我想讀者這個時候已經可以自己編寫任意維的動態陣列了。但是細心的讀者可能發現了一個問題,那就是我們所講的動態陣列都是一次性建立好的,如果接下來在使用的過程中我們使用的陣列需要擴充套件或者刪減一些不再使用元素該怎麼辦呢?!接下來我們先看一段關於動態陣列擴充套件的程式碼,在此以一維動態陣列的擴充套件為例,其它的以此類推。

#include <stdio.h>
#include <stdlib.h>
int main()
{
int*n,*p;
int i,n1,n2;
printf("請輸入所要建立的動態陣列的長度:");
scanf("%d",&n1);
n=(int*)calloc(n1,sizeof(int));
printf("請輸入所要擴充套件的動態陣列的長度:");
scanf("%d",&n2);
p=(int*)realloc(n,(n2)*sizeof(int));//動態擴充陣列
for(i=0;i<n2;i++)
{
p[i]=i+1;
if(i%5==0)
printf("\n");
printf("%d\t",p[i]);
}
free(p);
return 0;
}

執行結果如下:

請輸入所要建立的動態陣列的長度:6
請輸入所要擴充套件的動態陣列的長度:25

1       2       3       4       5
6       7       8       9       10
11      12      13      14      15
16      17      18      19      20
21      22      23      24      25      Press any key to continue

看了上面的程式碼讀者應該知道如何來擴充套件動態陣列了,可能有的讀者對於realloc()函式的使用有些陌生,如果有什麼疑惑的話可以參考我之前寫的一篇博文------C語言的那些小祕密之記憶體分配,在此我就不再做過多的講解了。

接下來如何縮小動態陣列。

#include <stdio.h>
#include <stdlib.h>
int main()
{
int*n,*p;
int i,n1,n2;
printf("請輸入所要建立的動態陣列的長度:");
scanf("%d",&n1);
n=(int*)calloc(n1,sizeof(int));
for(i=0;i<n1;i++)
{
n[i]=i+1;
if(i%5==0)
printf("\n");
printf("%d\t",n[i]);
}
printf("\n請輸入所要縮小的動態陣列的長度:");
scanf("%d",&n2);
p=(int*)realloc(n,(n2)*sizeof(int));
for(i=0;i<n2;i++)
{
if(i%5==0)
printf("\n");
printf("%d\t",p[i]);
}
printf("\n");
free(p);
return 0;
}

執行結果為:

請輸入所要建立的動態陣列的長度:25

1       2       3       4       5
6       7       8       9       10
11      12      13      14      15
16      17      18      19      20
21      22      23      24      25
請輸入所要縮小的動態陣列的長度:15

1       2       3       4       5
6       7       8       9       10
11      12      13      14      15
Press any key to continue

在這裡值得注意的一點就是在縮減動態陣列的時候,它是刪除了後面的元素,而前面的元素保持不變。在使用realloc()函式的時候要由其注意它的使用規則。

講到這兒就到了該說結束的時候了,由於本人水平有限,部落格中的不妥或錯誤之處在所難免,殷切希望讀者批評指正。同時也歡迎讀者共同探討相關的內容,如果樂意交流的話請留下你寶貴的意見。