1. 程式人生 > >C語言 二維陣列(指標)動態分配和釋放

C語言 二維陣列(指標)動態分配和釋放

C 二維陣列(指標)動態分配和釋放

先明確下概念:

所謂32位處理器就是一次只能處理32位,也就是4個位元組的資料,而64位處理器一次就能處理64位,即8個位元組的資料。如果我們將總長128位的指令分別按照16位、32位、64位為單位進行編輯的話:舊的16位處理器,比如Intel 80286 CPU需要8個指令,32位的處理器需要4個指令,而64位處理器則只要兩個指令,顯然,在工作頻率相同的情況下,64位處理器的處理速度會比16位、32位的更快。而且除了運算能力之外,與32位處理器相比,64位處理器的優勢還體現在系統對記憶體的控制上。由於地址使用的是特殊的整數,而64位處理器的一個ALU(算術邏輯運算器)和暫存器可以處理更大的整數,也就是更大的地址。傳統32位處理器的定址空間最大為4GB(2的32次方 = 4294967296bit = 4G左右),使得很多需要大容量記憶體的資料處理程式在這時都會顯得捉襟見肘,形成了執行效率的瓶頸。而64位的處理器在理論上則可以達到1800萬個TB,1TB等於1024GB,1GB等於1024MB,所以64位的處理器能夠徹底解決32位計算系統所遇到的瓶頸現象,速度快人一等,對於那些要求多處理器可擴充套件性、更大的可定址記憶體、視訊/音訊/三維處理或較高計算準確性的應用程式而言,64位處理器可提供卓越的效能。

32位(bit)和64位(bit)系統的指標佔的記憶體不一樣,注意B與b不同,B是Byte(位元組),b是bit(位) 1GB=1024MB,1MB=1024KB,1KB=1024B,1B=8bit

在32位的系統中,所有指標都佔4 bytes。cpu決定記憶體的編址,如32位CPU有32條地址匯流排,對應的地址格式為 10 01 .... 01 01 = 32bit =4byte,32位的系統其定址能力為32個二進位制位,應該是4個位元組的長度,指標大小是4byte.

64位 -> 01 01 10 10 ....01 = 64bit =8byte,64位的系統其定址能力為64個二進位制位,應該是8個位元組的長度,所以指標大小是8byte。以下都是內容都是32位系統指標。

(1)已知第二維

char (*a)[N];    //指向陣列的指標
 
a = (char (*)[N])malloc(sizeof(char *) * m);
 
printf("%d\n", sizeof(a));   //4,指標
 
printf("%d\n", sizeof(a[0]));//N,一維陣列
 
free(a);


(2)已知第一維

char* a[M];    //指標的陣列
 
int i;
 
for(i=0; i<M; i++)
 
    a[i] = (char *)malloc(sizeof(char) * n);
 
printf("%d\n", sizeof(a));   //4*M,指標陣列
 
printf("%d\n", sizeof(a[0]));//4,指標
 
for(i=0; i<M; i++)
 
    free(a[i]);


(3)已知第一維,一次分配記憶體(保證記憶體的連續性)

char* a[M];    //指標的陣列
 
int i;
 
a[0] = (char *)malloc(sizeof(char) * M * n);
 
for(i=1; i<M; i++)
 
    a[i] = a[i-1] + n;
 
printf("%d\n", sizeof(a));   //4*M,指標陣列
 
printf("%d\n", sizeof(a[0]));//4,指標
 
free(a[0]);


(4)兩維都未知

char **a;
 
int i;
 
a = (char **)malloc(sizeof(char *) * m);     //分配指標陣列
 
for(i=0; i<m; i++)
 
{
 
    a[i] = (char *)malloc(sizeof(char) * n); //分配每個指標所指向的陣列
 
}
 
printf("%d\n", sizeof(a));    //4,指標
 
printf("%d\n", sizeof(a[0])); //4,指標
 
for(i=0; i<m; i++)
 
{
 
    free(a[i]);
 
}
 
free(a);


(5)兩維都未知,一次分配記憶體(保證記憶體的連續性)

char **a;
 
int i;
 
a = (char **)malloc(sizeof(char *) * m);    //分配指標陣列
 
a[0] = (char *)malloc(sizeof(char) * m * n);//一次性分配所有空間
 
for(i=1; i<m; i++)
 
{
 
    a[i] = a[i-1] + n;
 
}//採用如上記憶體分配方法,意味著將a的值初始化為m*n的二維陣列首地址,且這塊記憶體連續
 
printf("%d\n", sizeof(a));    //4,指標
 
printf("%d\n", sizeof(a[0])); //4,指標
 
free(a[0]);
 
free(a);

採用(5)方法定義**data,分配M*256空間,除錯如下:

換算為十進位制分別為:

$1=140737353293840  $8  =6897728
$2=140737353294096  $9  =6897736
$3=140737353294352  $10=6897744

$1,$2,$3分別相差256

$8,$9,$10分別相差8(64位系統)

2.C++動態分配二維陣列2.C++動態分配二維陣列

(1)已知第二維

char (*a)[N];    //指向陣列的指標
 
a = new char[m][N];
 
printf("%d\n", sizeof(a));    //4,指標
 
printf("%d\n", sizeof(a[0])); //N,一維陣列
 
delete[] a;


(2)已知第一維

char* a[M];    //指標的陣列
 
for(int i=0; i<M; i++)
 
   a[i] = new char[n];
 
printf("%d\n", sizeof(a));    //4*M,指標陣列
 
printf("%d\n", sizeof(a[0])); //4,指標
 
for(i=0; i<M; i++)
 
   delete[] a[i];

(3)已知第一維,一次分配記憶體(保證記憶體的連續性)

char* a[M];    //指標的陣列
 
a[0] = new char[M*n];
 
for(int i=1; i<M; i++)
 
    a[i] = a[i-1] + n;
 
printf("%d\n", sizeof(a));    //4*M,指標陣列
 
printf("%d\n", sizeof(a[0])); //4,指標
 
delete[] a[0];


(4)兩維都未知

char **a;
 
a = new char* [m];    //分配指標陣列
 
for(int i=0; i<m; i++)
 
{
 
    a[i] = new char[n];   //分配每個指標所指向的陣列
 
}
 
printf("%d\n", sizeof(a));    //4,指標
 
printf("%d\n", sizeof(a[0])); //4,指標
 
for(i=0; i<m; i++)
 
    delete[] a[i];
 
delete[] a;

(5)兩維都未知,一次分配記憶體(保證記憶體的連續性)

char **a;
 
a = new char* [m];
 
a[0] = new char[m * n];    //一次性分配所有空間
 
for(int i=1; i<m; i++)
 
{
 
    a[i] = a[i-1] + n;         //分配每個指標所指向的陣列
 
}
 
printf("%d\n", sizeof(a));    //4,指標
 
printf("%d\n", sizeof(a[0])); //4,指標
 
delete[] a[0];
 
delete[] a;

多說一句:new和delete要注意配對使用,即有多少個new就有多少個delete,這樣才可以避免記憶體洩漏!

3.靜態二維陣列作為函式引數傳遞

如果採用上述幾種方法動態分配二維陣列,那麼將對應的資料型別作為函式引數就可以了。這裡討論靜態二維陣列作為函式引數傳遞,即按照以下的呼叫方式:

int a[2][3];
 
func(a);
C語言中將靜態二維陣列作為引數傳遞比較麻煩,一般需要指明第二維的長度,如果不給定第二維長度,則只能先將其作為一維指標傳遞,然後利用二維陣列的線性儲存特性,在函式體內轉化為對指定元素的訪問。 首先寫好測試程式碼,以驗證引數傳遞的正確性:

(1)給定第二維長度

void func(int a[][N])
 
{
 
    printf("%d\n", a[1][2]);
 
}

(2)不給定第二維長度


void func(int* a)
 
{
 
    printf("%d\n", a[1 * N + 2]);//計算元素位置
 
}

注意:使用該函式時需要將二維陣列首地址強制轉換為一維指標,即func((int*)a);注意:使用該函式時需要將二維陣列首地址強制轉換為一維指標,即func((int*)a);