c 編譯前確定陣列記憶體 c語言入坑指南 陣列之謎

2021-10-13 18:13:13 字數 2414 閱讀 4481

在c語言中,陣列和指標似乎總是「曖昧不清」,有時候很容易把它們混淆。本文就來理一理陣列和指標之間到底有哪些異同。

在分析之前,我們不妨回顧一下陣列的知識。陣列是可以儲存乙個固定大小的相同型別元素的順序集合。為了便於我們說明,假設有以下陣列宣告:

int a[5];

char b = "hello";

考慮下面的宣告:

int c[4];//假設int佔4位元組

int *d;

對於上面的宣告,編譯器會給c預留記憶體空間4*4位元組,並且陣列名代表著指向陣列第乙個元素的指標。但對於d,卻只為指標本身保留了記憶體空間。

所以此時有下面的操作:

c[3];        //合法

*(c+3); //合法

*d; //不合法,d指向了記憶體中不確定位置

c++; //不合法,一維陣列名是指標常量,常量不可修改

d++; //可通過編譯

另外,下面的兩種情況也是不一樣的:

char c = "hello";

char *d = "hello";

前者對字元陣列a進行了初始化,後者將d指向了字串常量。字串常量儲存在唯讀區,因此有下面的操作:

c[0] = 'h';  //合法,可修改陣列內容

*d = 'h'; //不合法,字串常量內容不可更改

d[0] = 'h' //不合法

絕大多數情況,陣列名都代表著指向該陣列中下標為0的元素的指標,但是有例外:

int e[4];//假設int為4位元組

sizeof(e);

上面的sizeof(e)的值並非4或8(指標占用空間),而是4*4 = 16。也就是說,當陣列名被用作運算子sizeof的引數時,它的計算結果是整個陣列的大小,而非第乙個元素的指標大小。

再來看下面這種情況:

int temp[5];

&temp+1;

temp+1;

在這裡,&temp指向整個陣列,因此+1後指向了陣列末尾,而temp指向陣列第乙個元素,+1後指向第二個元素。

如何計算陣列長度?考慮下面的**:

int f = ;

int *g = f;

size_t len_f = sizeof(f)/sizeof(int)//正確計算方法

size_t len_g = sizeof(g)/sizeof(int)

上面的len_f和len_g的值相等嗎?顯然並不相等。事實上,只有len_f得到了陣列f的長度,而len_g的值並沒有任何實際意義。

所謂的陣列不能作為引數,並不是指宣告的陣列不能作為引數傳遞,而是指當陣列名作為引數時,陣列名會被轉換為指向該陣列下標為0的元素的指標。

而下面的兩種宣告,其實也是等效的:

size_t arraylen(const int *arr);

size_t arraylen(const int arr);

我們來看乙個例子,說明陣列作為引數的情況:

#include int arraysum(const int arr)

for(loop = 0; loop < len; loop++)

return sum;

}int main(void)

; int sum = arraysum(a);

printf("arr sum is %d",sum);

return 0;

}

我們執行上面的程式,發現最終結果並不是我們預期的21,而是3。問題在於,a作為引數傳入到arraysum中時,它是作為指標的,那麼在函式內部計算sizeof(arr)自然只是得到了指標占用的記憶體大小。對於64位程式,這個大小是8,那麼len的值為2,最終只計算了兩個元素的和。

思考:該如何修改上面的程式才能得到正確的結果?

我們來總結一下前面的核心內容:

下面的**輸出結果是什麼?

#includeint main(void)

; int *p = (int*)(&a+1);

printf("%d,%d",*(a+1),*(p-1));

return 0;

}

推薦閱讀:

c語言入坑指南-「懸掛」else

c語言的main函式到底該怎麼寫

linux常用命令-解壓縮篇

C語言陣列的坑

定義 型別說明符 陣列名 常量表示式 複製 注意事項 常量表示式的值必須是正整數 陣列的起始元素下標為0 儲存方式同樣從低位址到高位址,並且所有陣列元素都儲存在乙個連續的記憶體單元中,陣列所占用的記憶體大小為陣列元素型別所占用的記憶體大小乘以陣列元素的個數。定義陣列型別 陣列名 n 複製 注意事項 ...

c語言向自定陣列 C語言陣列的定義及引用

c語言陣列的定義及引用 1.1 一維陣列的定義 初始化和引用 1.一維陣列的定義方式為 型別說明符 陣列名 常量表示式 1 陣列名的命名方法與變數名相同,遵循識別符號命名規則 2 陣列是用方括號括起來的常量表示式,不能用圓括號 3 常量表示式表示陣列元素的個數,即陣列的長度,陣列的下標從0開始,下標...

C語言編譯過程和記憶體分割槽

1預處理 巨集定義展開 標頭檔案展開 條件編譯等,同時將 中的注釋刪除,這裡並不會檢查語法 命令 gcc e hello.c o hello.i 2編譯 檢查語法,將預處理後檔案編譯生成彙編檔案 命令 gcc s hello.i o hello.s 3彙編 將彙編檔案生成目標檔案 二進位制檔案 命令...