從C語言的陣列引數退化為指標談起

2021-08-16 01:17:29 字數 1422 閱讀 8131

contact me:

blog ->

email -> cugtyt#qq.com, cugtyt#gmail.com

github -> cugtyt@github

知乎專欄 -> programming & tools

當我們寫下如下**:

void fun(int arr);

// 等同於void fun(int *arr);

int a[10];

fun(a);

我們知道a原來是個陣列,但是當我們呼叫fun傳入的時候,arr不再是陣列的形式,而是退化為指標,假設讀者有這個理解基礎。

那麼問題來了,這個轉變過程我們要注意什麼?

首先考慮如果是個陣列我們可以求陣列長度:

// 為了避免歧義,假設int是4個位元組,指標也是4個位元組

sizeof(a); // 40

sizeof(a) / sizeof(a[0]); // 10

但是指標就不一樣了:

sizeof(arr);    // 4
我們丟失了陣列長度的資訊,因此從本質上來說,我們用退化的指標來表示陣列是有點問題的,真實的陣列指標應該怎麼寫呢?

void fun(int (*arr)[10]);

int a[10];

fun(&a);

#include 

void fun1(int *arr)

void fun2(int (*arr)[10])

int main()

output:

0x7fffeadf1b30

0x7fffeadf1b34

0x7fffeadf1b30

0x7fffeadf1b58

可以看到fun1,就是原來的方式,指標增加1,沿著陣列元素後移,我們無法得知陣列有多長,而fun2是傳入陣列指標,指標增加1,位址增加28,注意這裡是16進製制,轉為10進製就是40,正好就是陣列的長度,也就是說這個指標包含了陣列長度的資訊。

好像我在表達原來的寫法是錯的,這樣才對,但是並不是。因為雖然保留了陣列資訊,但是函式的宣告必須把陣列長度表示出來,這意味著我們必須事先知道長度,而且不能改變,這就限制了函式的能力。所以c的處理方式是退化陣列為指標,然後加上陣列長度!

c++加入了std::array的容器,但是正如我們上面討論的,由於我們要把長度寫死,因此在函式傳遞的時候就很不方便了,這個容器帶來的好處除了可以用標準庫的函式外,似乎在這方面並沒有什麼值得稱讚的地方。當然用指標,我們得人工保證傳入的東西是正確的。

希望讀者通過這個簡短的分析理解為什麼會有陣列退化為指標。

C語言 引數傳遞使陣列名退化為指標

做題的時候發現了一道題,想了很久也沒有想出來與給出演算法相符合的思路 最後寫了個可以勉強得出結果,但是好像不怎麼對的方法 因為題目給出的變數都已經使用過,所以只能使用陣列名作為增量向後遍歷 但是這時就出現了問題,陣列名竟然不指向首位址元素了,事後想想也知道如果一直指向首元素那麼顯然不能通過這種自增陣...

C語言 陣列做函式引數退化為指標的技術推演

陣列做函式引數退化為指標的技術推演 include include include 一維陣列做函式引數退化為指標的技術推演 void printfa char strarr 3 計算機中,陣列都是線性儲存,二維陣列元素也是乙個個的排列的 例如 1,2,3,4,5,6,7,8,9 像這組資料 我們可以...

引數傳遞時陣列引用保護陣列退化為指標

如下定義就得到乙個陣列的引用 型別名 變數明 n 在進行引數的傳遞時,陣列引用可以幫助我們防止陣列退化為指標,而這是我們在程式設計中很難注意到的問題。下面來看乙個例項 include void each int int ref 10 each int array 問題1 sizeof 的值?each...