【C/C++】搞不懂指針,指針只是一種普通的變量

在學(xué)習(xí)C/C++的過(guò)程中,指針常常讓初學(xué)者感到困惑。其實(shí),指針并沒(méi)有那么復(fù)雜,理解了它的基本原理和使用方法之后,你會(huì)發(fā)現(xiàn)它不過(guò)是一個(gè)存儲(chǔ)地址的變量而已。

一、變量的本質(zhì)

實(shí)際上,所有的變量都是一個(gè)地址,并不是小白理解的int a 是一個(gè)變量而int* a是一個(gè)地址。實(shí)際上所有的變量都是一個(gè)地址。

變量的作用是為了指向一塊存儲(chǔ)空間,修改和讀取內(nèi)存中的數(shù)據(jù)。而指向存儲(chǔ)空間需要的是一段真實(shí)內(nèi)存地址,而操作系統(tǒng)為了避免真實(shí)內(nèi)存沖突,所以每個(gè)進(jìn)程必須使用虛擬內(nèi)存地址,由硬件內(nèi)存管理單元和操作系統(tǒng)共同決定虛擬地址和真實(shí)地址的映射。

因此,所有的變量實(shí)際上都是一個(gè)虛擬內(nèi)存地址。而int a這個(gè)變量的虛擬內(nèi)存地址指向的是一個(gè)可以存儲(chǔ)一個(gè)int格式數(shù)據(jù)的內(nèi)存空間,而int* a這個(gè)變量的虛擬內(nèi)存地址指向的是一個(gè)虛擬內(nèi)存地址,這個(gè)虛擬內(nèi)存地址指向的是一個(gè)可以存儲(chǔ)一個(gè)int格式數(shù)據(jù)的內(nèi)存空間。

你會(huì)發(fā)現(xiàn)上面這段話,有兩段一模一樣的描述。如果你看懂了上面這段話,就可以理解int* a儲(chǔ)存的其實(shí)是一個(gè)int類(lèi)型變量的原型。實(shí)際上int** a儲(chǔ)存的就是一個(gè)int*型變量的原型。

你始終要知道的是,所有變量都是一個(gè)虛擬內(nèi)存地址,區(qū)別就是指向的內(nèi)存空間作用不同而已,intint*沒(méi)有任何本質(zhì)上的不同。


二、指針的基本原理

1. 什么是指針?

在C/C++中,指針是一種變量,它存儲(chǔ)的是另一個(gè)變量的地址。簡(jiǎn)單來(lái)說(shuō),普通變量存儲(chǔ)的是數(shù)據(jù)本身,而指針存儲(chǔ)的是數(shù)據(jù)所在的內(nèi)存地址。

2. 指針的定義和使用

指針變量的定義需要指定指針?biāo)赶虻臄?shù)據(jù)類(lèi)型,語(yǔ)法如下:

數(shù)據(jù)類(lèi)型* 指針變量名;

例如:

int a = 10;      // 定義一個(gè)整型變量
int* p = &a;     // 定義一個(gè)指向整型的指針變量,并將a的地址賦值給它

在上面的代碼中:

  • &a 表示取變量a的地址。
  • p 是一個(gè)指針變量,它存儲(chǔ)了變量a的地址。

你可以通過(guò)*p來(lái)訪問(wèn)指針指向的變量的值:

cout << *p << endl;  // 輸出10,表示訪問(wèn)指針p指向的變量a的值

3. 指針的本質(zhì)

指針本質(zhì)上是一個(gè)普通變量,只不過(guò)它存儲(chǔ)的是一個(gè)地址。理解了這一點(diǎn),就不難理解為什么指針可以和地址、內(nèi)存操作聯(lián)系起來(lái)。

例如:

cout << p << endl;   // 輸出p存儲(chǔ)的地址(a的地址)
cout << *p << endl;  // 輸出p指向地址中存儲(chǔ)的值(a的值)

4. 解引用運(yùn)算符和取址符

int a = 10;
int* p = &a;
cout << *p << endl;

*是一個(gè)運(yùn)算符,可以讀取p這個(gè)變量?jī)?chǔ)存的地址指向的值。
在非形參的定義中,&是取地址符上面的&a實(shí)際上就是拿到變量a的原型,文章開(kāi)頭說(shuō)過(guò)所有的變量其實(shí)都是一個(gè)地址(注意a雖然原型是個(gè)地址但a代表的地址是不可修改的,它被賦值給了一個(gè)指針p,而指針儲(chǔ)存的地址是可以修改的,他是指針類(lèi)型變量的值,修改了這個(gè)值并不會(huì)影響變量a)。


二、指針的使用場(chǎng)景

指針不僅是C/C++的核心,也是程序設(shè)計(jì)中非常重要的一部分。以下是指針的常見(jiàn)使用場(chǎng)景:

1. 動(dòng)態(tài)內(nèi)存分配

在C++中,可以使用指針動(dòng)態(tài)分配內(nèi)存:

int* p = new int(42);  // 動(dòng)態(tài)分配一個(gè)整數(shù)并初始化為42
cout << *p << endl;    // 輸出42
delete p;              // 釋放內(nèi)存

動(dòng)態(tài)分配內(nèi)存時(shí),必須用delete釋放,否則可能會(huì)導(dǎo)致內(nèi)存泄漏。

2. 通過(guò)指針修改變量的值

指針可以用來(lái)間接修改變量的值:

void modify(int* p) {
    *p = 20;  // 修改指針指向的變量的值
}

int main() {
    int a = 10;
    modify(&a);  // 將a的地址傳遞給函數(shù)
    cout << a << endl;  // 輸出20
    return 0;
}

3. 指針與函數(shù)

指針可以用來(lái)實(shí)現(xiàn)函數(shù)參數(shù)的傳址調(diào)用:

void swap(int* x, int* y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main() {
    int a = 5, b = 10;
    swap(&a, &b);  // 通過(guò)指針交換a和b的值
    cout << a << " " << b << endl;  // 輸出10 5
    return 0;
}

三、C++中的引用

1. 什么是引用?

引用是C++中一種更高級(jí)的功能,可以看作是指針的“語(yǔ)法糖”。引用本質(zhì)上是一個(gè)變量的別名,它提供了一種更安全、更簡(jiǎn)潔的方式來(lái)操作變量。

引用的定義語(yǔ)法:

數(shù)據(jù)類(lèi)型& 引用名 = 變量名;

例如:

int a = 10;
int& ref = a;  // 定義一個(gè)引用ref,作為變量a的別名

此時(shí),refa是同一個(gè)實(shí)體,修改ref的值會(huì)直接影響a

ref = 20;      // 修改ref的值
cout << a << endl;  // 輸出20

2. 引用的使用場(chǎng)景

  • 作為函數(shù)參數(shù):引用可以實(shí)現(xiàn)函數(shù)參數(shù)的傳址調(diào)用,同時(shí)避免使用指針的繁瑣語(yǔ)法。
void modify(int& ref) {
    ref = 30;  // 修改引用ref的值
}

int main() {
    int a = 10;
    modify(a);  // 直接將變量傳遞給引用參數(shù)
    cout << a << endl;  // 輸出30
    return 0;
}
  • 作為函數(shù)返回值:引用可以用來(lái)返回一個(gè)變量的引用,從而直接操作原變量。
int& getValue(int& ref) {
    return ref;
}

int main() {
    int a = 10;
    int& b = getValue(a);
    b = 40;  // 修改b的值,等同于修改a
    cout << a << endl;  // 輸出40
    return 0;
}

四、數(shù)組與指針的關(guān)系

1. 數(shù)組的內(nèi)存布局

數(shù)組在內(nèi)存中是連續(xù)存儲(chǔ)的,數(shù)組名本質(zhì)上是一個(gè)指向數(shù)組第一個(gè)元素的"指針"。很多教程會(huì)把數(shù)組和指針劃上關(guān)系,實(shí)際上我們前文已經(jīng)論證過(guò),實(shí)際上數(shù)組也就是一種變量類(lèi)型,所有的變量名實(shí)際上都是指向第一個(gè)元素的"指針",只不過(guò)不是數(shù)組的話,它本身就只有一個(gè)元素而已。

int arr[3] = {1, 2, 3};
cout << arr << endl;       // 輸出數(shù)組首元素的地址
cout << &arr[0] << endl;   // 同樣輸出數(shù)組首元素的地址

2. 用指針遍歷數(shù)組

指針可以用來(lái)遍歷數(shù)組。很多教程會(huì)把下面的代碼來(lái)表示數(shù)組和指針的關(guān)系,實(shí)際上那是因?yàn)閿?shù)組申請(qǐng)的時(shí)候,虛擬內(nèi)存地址是連續(xù)的,所以可以通過(guò)運(yùn)算符來(lái)指向下一個(gè)單元。如果這不是一個(gè)數(shù)組,你一樣可以修改p中存儲(chǔ)的地址,只不過(guò)那樣就脫離和原變量的關(guān)系甚至造成程序異常。

int arr[3] = {1, 2, 3};
int* p = arr;  // 指針指向數(shù)組首元素
for (int i = 0; i < 3; i++) {
    cout << *(p + i) << " ";  // 使用指針訪問(wèn)數(shù)組元素
}

3. 指針與數(shù)組名的區(qū)別

雖然數(shù)組名可以看作指針,但它與普通指針有一些區(qū)別:

  • 數(shù)組名是常量指針,不能修改。這一點(diǎn)我們之前也提過(guò),變量本身所代表的地址,是不能修改的
  • 普通指針可以動(dòng)態(tài)指向其他地址,而數(shù)組名始終指向數(shù)組的起始地址。

例如:

int arr[3] = {1, 2, 3};
int* p = arr;  // 正確
p++;           // 正確,可以移動(dòng)指針
arr++;         // 錯(cuò)誤,數(shù)組名是常量,不能修改

4. 二維數(shù)組與指針

二維數(shù)組的每一行可以看作是一個(gè)一維數(shù)組,指針可以用來(lái)訪問(wèn)二維數(shù)組:

int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*p)[3] = arr;  // 定義一個(gè)指向含有3個(gè)元素的數(shù)組的指針
cout << p[0][1] << endl;  // 輸出2
cout << p[1][2] << endl;  // 輸出6

這里int (*p)[3]實(shí)際上可以重新賦值其它數(shù)組,比如再聲明一個(gè)int arr2[9][3]一樣可以賦值給p

int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int (*p)[3] = arr;  // 定義一個(gè)指向含有3個(gè)元素的數(shù)組的指針

    cout << p[0][1] << endl;  // 輸出2
    cout << p[1][2] << endl;  // 輸出6

    // 定義一個(gè)新數(shù)組
    int arr2[9][3] = {
        {10, 11, 12}, {13, 14, 15}, {16, 17, 18},
        {19, 20, 21}, {22, 23, 24}, {25, 26, 27},
        {28, 29, 30}, {31, 32, 33}, {34, 35, 36}
    };

    // 讓 p 指向 arr2
    p = arr2;

    // 驗(yàn)證 p 是否正確指向 arr2
    cout << p[0][1] << endl;  // 輸出11
    cout << p[8][2] << endl;  // 輸出36

五、總結(jié)

指針是C/C++中非常強(qiáng)大的工具,理解了它的本質(zhì)——存儲(chǔ)地址的變量,就能更好地掌握它的用法。C++中的引用作為指針的更高層次封裝,提供了更簡(jiǎn)潔的語(yǔ)法和更高的安全性。

關(guān)鍵點(diǎn)總結(jié):

  1. 任何變量名實(shí)際上都代表一個(gè)虛擬地址,無(wú)論是整數(shù),指針,數(shù)組,復(fù)合結(jié)構(gòu),本質(zhì)上都是一樣的。
  2. 指針是存儲(chǔ)地址的變量,*&是操作指針的關(guān)鍵。
  3. C++中的引用是指針的語(yǔ)法糖,更易用且更安全。
  4. 指針和數(shù)組可以結(jié)合使用進(jìn)行靈活操作。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容