1. 程式人生 > >C之數組參數和指針參數(三十一)

C之數組參數和指針參數(三十一)

C語言 數組參數 指針參數

我們在前面講了在 C 語言中,數組參數會退化為指針。那麽這是為什麽呢?在 C 語言中只會以值拷貝的方式傳遞參數,當向函數傳遞數組時,不是將整個數組拷貝一份傳入函數而是將數組名看做常量指針傳數組首元素地址。

那麽當初在設立 C 語言時,主要是用於 Unix 操作系統,而 Unix 效率要求很高。所以 C 語言以高效作為最初設計目標:a> 參數傳遞的時候如果拷貝整個數組執行效率將會大大下降;b> 參數位於棧上,太大的數組拷貝將導致棧溢出。函數調用棧是用一片內存來存放的,如果棧溢出,那麽函數調用將無法執行,程序將會崩了。

二維數組參數同樣也存在退化,它可以看做是一維數組,它中的每個元素是一維數組。二維數組參數中第一維的參數可以省略,如:void f(int a[5]) ==> void f(int a[]) ==> void f(int* a); void g(int a[3][3]) ==> void g(int [][3]) ==> void g(int (*a)[3])

;那麽我們平時所說的一維數組作為參數時將會退化為一維指針,二維數組並不會退化為二維指針,而是退化為數組指針。那麽什麽樣的參數將退化為二維指針呢?我們總結了下面這張表

數組參數
等效的指針參數
一維數組:float a[5]
指針:float* a
指針數組:int* a[5]
指針的指針:int** a
二維數組:char a[3][4]
數組的指針:char(*a)[4]

我們可以看出指針數組作為參數時才退化為二維指針。那麽在 C 語言中無法向一個函數傳遞任意多的多維數組,必須提供除第一維之外的所有維長度;其中第一維之外的維度信息用於完成指針運算,N維數組的本質是一維數組,元素是 N - 1 維的數組,對於多維數組的函數參數只有第一維是可變的。下來我麽以代碼為例進行分析,代碼如下

#include <stdio.h>

void access(int a[][3], int row)
{
    int col = sizeof(*a) / sizeof(int);
    int i = 0;
    int j = 0;
    
    printf("sizeof(a) = %d\n", sizeof(a));
    printf("sizeof(*a) = %d\n", sizeof(*a));
    
    for(i=0; i<row; i++)
    {
        for(j=0; j<col; j++)
        {
            printf("%d\n", a[i][j]);
        }
    }
    
    printf("\n");
}

int main()
{
    int a[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
    int aa[2][2] = {0};
    
    access(a, 3);
    access(aa, 2);
    
    return 0;
}

我們看到在程序中我們在第25和26行分別定義了3*3,2*2的二維數組,但是 access 函數裏參數的數組參數第二維指定是3。所以我們在第29行調用這個函數會報錯,因為類型不匹配。我們來看看編譯結果

技術分享圖片

我們看到它報警告了,也就是說這個程序雖然通過編譯了,但是它允許的結果是不確定的。我們看到我們定義的 aa 數組是 2*2 的,但是它打印出了6個數,也就是當成 2*3 的了。所以我們這樣調用是不對的。

下來我們看個三維數組的代碼,代碼如下

#include <stdio.h>

void access_ex(int b[][2][3], int n)
{
    int i = 0;
    int j = 0;
    int k = 0;
    
    printf("sizeof(b) = %d\n", sizeof(b));
    printf("sizeof(*b) = %d\n", sizeof(*b));
    
    for(i=0; i<n; i++)
    {
        for(j=0; j<2; j++)
        {
            for(k=0; k<3; k++)
            {
                printf("%d\n", a[i][j][k]);
            }
        }
    }
    
    printf("\n");
}

int main()
{
    int aa[2][2] = {0};
    int b[1][2][3] = {0};
    
    access_ex(b, 1);
    access_ex(aa, 2);
    
    return 0;
}

我們在 access_ex 函數裏指定的是第二維是2,第三維是3。但是我們定義的數組 aa 不是這樣的,我們看看編譯結果技術分享圖片

我們看到第二個編譯出的結果也是不確定的。通過本節對數組參數和指針參數的學習,總結如下:1、C 語言中只會以值拷貝的方式傳遞參數,並且數組參數必然退化為指針;2、多維數組參數必須提供除第一維之外的所有維長度;3、對於多維數組的函數參數值第一維是可變的。


歡迎大家一起來學習 C 語言,可以加我QQ:243343083

C之數組參數和指針參數(三十一)