數(shù)組和指針本質(zhì)不同,但可互相轉(zhuǎn)換;數(shù)組是固定大小的連續(xù)內(nèi)存,不能修改地址,而指針是變量,可隨時(shí)改變指向。1. 數(shù)組名是常量地址,不可賦值;2. 指針保存內(nèi)存地址,可修改其指向;3. 數(shù)組在多數(shù)表達(dá)式中會(huì)退化為指針;4. 傳數(shù)組給函數(shù)時(shí)形參自動(dòng)轉(zhuǎn)為指針;5. 指針無法還原數(shù)組長(zhǎng)度,需手動(dòng)記錄信息;6. 字符串字面量用指針指向只讀內(nèi)存;7. 注意數(shù)組指針與指針數(shù)組的區(qū)別。理解這些異同有助于寫出更清晰安全的c代碼。
在c語(yǔ)言中,數(shù)組和指針看起來很像,但它們其實(shí)是兩個(gè)不同的概念。簡(jiǎn)單來說,數(shù)組是存儲(chǔ)一組相同類型數(shù)據(jù)的連續(xù)內(nèi)存空間,而指針是一個(gè)變量,它保存的是某個(gè)內(nèi)存地址。雖然它們本質(zhì)不同,但在很多使用場(chǎng)景下可以互相轉(zhuǎn)換和操作。
數(shù)組和指針的本質(zhì)區(qū)別
數(shù)組是一塊固定大小的內(nèi)存區(qū)域,編譯器會(huì)記住它的長(zhǎng)度和起始位置。例如:
int arr[5] = {1, 2, 3, 4, 5};
這個(gè)arr不是變量,而是常量地址,不能被賦值,比如你不能寫arr = NULL;。
立即學(xué)習(xí)“C語(yǔ)言免費(fèi)學(xué)習(xí)筆記(深入)”;
而指針是一個(gè)變量,它保存的是一個(gè)地址:
int *p = arr;
這時(shí)候p可以隨意改變指向,比如你可以寫p++;或者p = NULL;,這不會(huì)影響原來的數(shù)組。
所以總結(jié)一下:
- 數(shù)組名不是一個(gè)變量,不能修改
- 指針是一個(gè)變量,可以隨時(shí)改變它的值(也就是指向)
數(shù)組怎么轉(zhuǎn)成指針?
數(shù)組在大多數(shù)表達(dá)式中都會(huì)“退化”成指針,也就是說,除了作為sizeof或&運(yùn)算的操作數(shù)外,數(shù)組名會(huì)自動(dòng)變成指向其第一個(gè)元素的指針。
比如:
int arr[5]; int *p = arr; // 這里arr就退化成了int*
也可以用取地址的方式獲取指針:
int *p = &arr[0]; // 和上面等價(jià)
還有一種情況是把數(shù)組傳給函數(shù)時(shí),形參會(huì)被編譯器自動(dòng)處理為指針:
void func(int arr[]) { // 實(shí)際上arr會(huì)被當(dāng)作int* }
指針能還原成數(shù)組嗎?
嚴(yán)格來說,指針本身并不知道它指向的內(nèi)存有多大,所以在運(yùn)行時(shí)無法從指針直接還原出數(shù)組的長(zhǎng)度。除非你自己記錄了相關(guān)信息。
舉個(gè)例子:
int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; // 你只能通過p訪問元素,但不知道它后面有幾個(gè)元素 for (int i = 0; i < 5; i++) { printf("%dn", p[i]); }
這里必須你知道數(shù)組長(zhǎng)度是5,否則無法安全地遍歷整個(gè)數(shù)組。
所以結(jié)論是:
- 從指針到數(shù)組的轉(zhuǎn)換更多是邏輯上的理解,而不是語(yǔ)法層面的轉(zhuǎn)換
- 需要你自己保留數(shù)組長(zhǎng)度信息才能安全使用指針訪問數(shù)組內(nèi)容
使用時(shí)容易混淆的地方
有時(shí)候你會(huì)看到類似這樣的寫法:
char *str = "hello";
這是字符串字面量,雖然用的是指針,但它指向的是只讀內(nèi)存中的字符數(shù)組。這種情況下,你不應(yīng)該試圖修改內(nèi)容,比如str[0] = ‘H’;會(huì)導(dǎo)致未定義行為。
還有數(shù)組指針和指針數(shù)組的區(qū)別也容易搞混:
int (*p1)[5]; // p1是指向有5個(gè)int的數(shù)組的指針 int *p2[5]; // p2是5個(gè)指向int的指針組成的數(shù)組
這兩個(gè)寫法差別挺大,注意括號(hào)的位置。
基本上就這些。數(shù)組和指針關(guān)系密切,但又不完全一樣。理解它們之間的異同和轉(zhuǎn)換方式,有助于寫出更清晰、安全的C代碼。