国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - C/C++ - C++指針與數(shù)組:指針詳解

C++指針與數(shù)組:指針詳解

2021-12-31 15:13追道者 C/C++

本文從初學(xué)者的角度,深入淺出地講解C++中的指針、數(shù)組指針,對(duì)最常混淆的引用傳遞、值傳遞和指針傳遞做了區(qū)處,需要的朋友可以參考下

本文主要介紹C語(yǔ)言中指針的基本概念與用法,本博文從零開(kāi)始講解指針,只要你了解基本的C語(yǔ)法,相信你看完本文后一定會(huì)有所收獲。

 

一. What(什么是指針)

1. 地址初了解

要搞明白什么是指針,首先我們得先了解一個(gè)概念:地址。

什么是地址呢?

我們知道,計(jì)算機(jī)的內(nèi)存是一塊連續(xù)的大塊存儲(chǔ)空間,為了提高 CPU 查找數(shù)據(jù)的效率,我們將這塊連續(xù)的存儲(chǔ)空間以字節(jié)為單位進(jìn)行編號(hào),每個(gè)字節(jié)都一一對(duì)應(yīng)了一個(gè)編號(hào),這個(gè)編號(hào)就叫做地址。

舉個(gè)形象的例子:

如果我們把一座宿舍樓看做是內(nèi)存,那么宿舍樓里的房間我們就可以看成是內(nèi)存里的每一個(gè)字節(jié),那么每個(gè)房間的門(mén)牌號(hào)就可以看做是地址。

為什么要有地址?

通過(guò)上面的例子,我們很容易了解到地址存在的意義。試想,如果宿舍樓里的房間都沒(méi)有門(mén)牌號(hào),我們就很難描述一指定房間的具體位置。CPU 對(duì)內(nèi)存的處理也是如此,如果沒(méi)有地址,CPU 就沒(méi)有辦法確定指定內(nèi)存的具體位置,從而正確且快速的訪問(wèn)到該內(nèi)存空間。

2. 指針概念

  • 指針就是地址
  • 指針就是地址
  • 指針就是地址

重要的事情說(shuō)三遍,我們必須明確的知道一件事,指針就是地址,可以理解為,指針是地址在C語(yǔ)言里的一種特殊叫法。

#include <stdio.h>
int main()
{
	int a = 10;
	int *p = &a;		// p是不是指針?
	printf("%p\n", p);  // %p 可以格式化輸出地址。
	return 0;
}

既然如此,上述代碼中 p 是不是指針呢?

我們說(shuō)過(guò)指針就是地址,而 p 是不是地址?當(dāng)然不是!地址是一個(gè)單獨(dú)的數(shù)據(jù),就像 int a = 10; 我們能說(shuō) a 就是 10 嗎?當(dāng)然不能,10是一個(gè)整形常量,而 a 是一個(gè)整形變量,我們只能說(shuō) a 里面存放的值是 10,而不能簡(jiǎn)單的說(shuō) a 就是 10。

同理,上述代碼中的 p 是一個(gè)變量,里面存放的是 a 的地址,我們稱它為指針變量。所以嚴(yán)格意義上來(lái)說(shuō),p 不是指針,而是指針變量。就像 a 不是整數(shù)10,而是整形變量一樣

那么什么是指針呢,我們把這段代碼運(yùn)行起來(lái):

C++指針與數(shù)組:指針詳解

沒(méi)錯(cuò),嚴(yán)格意義上來(lái)說(shuō),這段數(shù)字才真正的叫做指針 (地址值在計(jì)算機(jī)中一般以16進(jìn)制顯示)。

3. 指針與指針變量

通過(guò)上面的講解,相信大家可以理解,指針是地址,是一個(gè)常量,而指針變量是一個(gè)變量,里面存放的是指針,這兩者之間有著本質(zhì)區(qū)別。

看到這,相信有些同學(xué)就有疑問(wèn)了:明明上課的時(shí)候,或者某些書(shū)上都將指針變量統(tǒng)稱為指針,就像 上例中的 p 平時(shí)都叫做指針,為什么現(xiàn)在又說(shuō) p 不是指針呢?

請(qǐng)大家注意,我說(shuō) p 不是指針是在嚴(yán)格意義上來(lái)說(shuō)。

在日常使用中,我們經(jīng)常把指針和指針變量混為一談。這似乎成為了一種習(xí)慣,甚至我在下面的表述中都可能將指針變量表述為指針。

結(jié)論是:我們?cè)谌粘J褂弥校梢阅:羔樑c指針變量的概念,把指針變量統(tǒng)稱為指針,但是,我們心里必須清楚的意識(shí)到,指針和指針變量的本質(zhì)區(qū)別,以及你叫的這個(gè)東西到底是指針還是指針變量。

 

二. Why(為什么要有指針)

經(jīng)過(guò)上面的講解,相信這個(gè)問(wèn)題就非常簡(jiǎn)單了。指針就是地址,那么為什么要有地址?究其原因就是,為了提高查找效率

試想如果沒(méi)有地址的存在,我們寫(xiě)下 int a = 10; 的時(shí)候,系統(tǒng)會(huì)自動(dòng)在內(nèi)存中開(kāi)辟一4字節(jié)的空間存放10這個(gè)數(shù)值。而我們 CPU 在訪問(wèn)的時(shí)候,由于沒(méi)有地址的存在只能在內(nèi)存中一塊一塊的遍歷對(duì)比查找,而有了地址,內(nèi)存就可以把地址值告訴 CPU,CPU 就可以根據(jù)地址值直接定位到該內(nèi)存,大大提高了 CPU 訪問(wèn)內(nèi)存的效率與準(zhǔn)確性。

 

三. How(如何使用指針)

1. 基本定義

指針變量的定義格式較簡(jiǎn)單,只要在類型和變量名之間加上 * 操作符,就可以定義該類型的指針變量。

int *a = NULL;				//定義整形指針變量
double *d = NULL;			//定義雙精度浮點(diǎn)型指針變量
struct stdnt *ps = NULL;	//定義結(jié)構(gòu)體指針變量

注: NULL 是指針變量初始化的時(shí)候常用的宏定義,稱其為空指針,本質(zhì)為 0 值。

如果定義時(shí)不初始化,如:

int *a;

我們知道,變量如果不初始化,其中的值就是隨機(jī)值,也就是此時(shí)的指針變量 a 里面存放的是隨機(jī)值,如果此時(shí)訪問(wèn) a 變量就會(huì)以這個(gè)隨機(jī)值作為地址訪問(wèn)對(duì)應(yīng)的內(nèi)存,這種操作是非法的。這種不初始化的指針我們稱之為野指針。

所以,為了避免野指針的出現(xiàn),我們?cè)诙x指針變量時(shí)盡量對(duì)其進(jìn)行初始化。

2. 取地址操作符 &

我們使用指針就是使用地址,那么地址從何而來(lái)?我們可不可以這么寫(xiě)代碼:

int *a = 0x11223344;

我們把 0x11223344 看做是地址值交給整形指針變量 a 來(lái)存儲(chǔ)。語(yǔ)法上沒(méi)有問(wèn)題,但是這樣寫(xiě)毫無(wú)意義!因?yàn)?0x11223344 這個(gè)地址對(duì)于我們來(lái)說(shuō)是未知的,我們并沒(méi)有讀取和訪問(wèn)的權(quán)限,這時(shí)候的 a 變量就相當(dāng)于一個(gè)野指針。

事實(shí)上,我們的地址是由 & 取地址符取出來(lái)的。

#include <stdio.h>
int main()
{
	int a = 10;
	int *p = &a;
	return 0;
}

這里我們定義了整形變量 a,取地址符取出了 a 的地址并把它賦給整形指針變量 p。

這里就有一個(gè)疑問(wèn),a 是一個(gè)整形變量,占4字節(jié)的空間,而通過(guò)上面的介紹,我們知道內(nèi)存的地址編號(hào)是以字節(jié)為單位的,這就意味著變量 a 其實(shí)存在4個(gè)地址,那么 &a 究竟取出的是哪一個(gè)地址呢?

上結(jié)論:

在C語(yǔ)言中,對(duì)任意類型的變量或者數(shù)組取地址,永遠(yuǎn)取得是數(shù)值上最小的那個(gè)地址。

我們畫(huà)一下上面代碼的內(nèi)存分布圖:

C++指針與數(shù)組:指針詳解

假設(shè)從左向右地址依次升高,那么 p 里面存放的就是 a 變量4字節(jié)中地址最低的那個(gè)字節(jié)的地址。

3. 解引用操作符 *

我們上面說(shuō)到,對(duì)變量取地址取得是地址最低的字節(jié)即首字節(jié)地址,那么我們?nèi)绾瓮ㄟ^(guò)這一個(gè)字節(jié)的地址訪問(wèn)到原變量里的數(shù)據(jù)呢,這里就需要使用 * 操作符:

#include <stdio.h>
int main()
{
	int a = 10;
	int *p = &a;
	*p = 20;     // 等價(jià)于 a = 20
	printf("%d\n", *p);
	printf("%d\n", a);
	return 0;
}

看上面的代碼,我們把 a 變量的地址賦值給指針變量 p,通過(guò) *p 即可訪問(wèn)到該變量的內(nèi)容。

那么 * 操作符到底是如何使用的呢,下面給出結(jié)論:

對(duì)指針解引用,就是指針指向的目標(biāo)。

就像上例中 *p 是什么?*p 就是 a,*p 就是 a,*p就是a,重要的事情說(shuō)三遍。所以,如果我改變 *p 的值,完全等價(jià)于直接改變 a 變量的值。

上面的代碼運(yùn)行結(jié)果:

C++指針與數(shù)組:指針詳解

那么,我們看下面這段代碼:

int main()
{
	int a = 0x11223344;
	int *p = &a;
	printf("0x%x\n", *(char*)p);
	return 0;
}

注意,我們說(shuō) *p 就是 a,但是,這里的 *p 被強(qiáng)制類型轉(zhuǎn)化為 char* 類型之后再進(jìn)行的解引用操作,此時(shí)的 p 就是一個(gè)字符類型的指針,因?yàn)樽址?char 類型在C中只占一個(gè)字節(jié),對(duì)其進(jìn)行解引用只能訪問(wèn)一個(gè)字節(jié)的內(nèi)容。而我們說(shuō)過(guò) p 中存放的是 a 變量的首字節(jié)的地址,即 44 的地址 (至于為什么,請(qǐng)讀者自己了解大小端的內(nèi)容),解引用就只訪問(wèn)到了 44:

C++指針與數(shù)組:指針詳解

4. 結(jié)構(gòu)體指針

下面定義一個(gè)結(jié)構(gòu)體:

typedef struct Student
{
	int age;
	char name[20];
	char sex[2];
}STD;

C語(yǔ)言中任何數(shù)據(jù)類型都有其對(duì)于的指針類型,結(jié)構(gòu)體也不例外,如下:

int main()
{
	STD s = { 18, "張三", "男" };
	STD *ps = &s;		// 定義結(jié)構(gòu)體指針
	printf("%s\n%d\n%s\n", s.name, s.age, s.sex);
}

我們定義一個(gè)結(jié)構(gòu)體變量并初始化,通過(guò) . 操作符可以很容易訪問(wèn)到結(jié)構(gòu)體的內(nèi)容。那么我們?nèi)绾瓮ㄟ^(guò)結(jié)構(gòu)體指針變量 ps 來(lái)訪問(wèn)結(jié)構(gòu)體的內(nèi)容呢?

我們說(shuō)過(guò)對(duì)指針解引用,就是指針指向的目標(biāo),那么請(qǐng)讀者思考,*ps 是什么呢?沒(méi)錯(cuò) *ps 就是 s變量,既然如此,我們就可以這么訪問(wèn):

	printf("%s\n%d\n%s\n", (*ps).name, (*ps).age, (*ps).sex);
	//注:因 . 操作符優(yōu)先級(jí)高于 * 操作符,故 (*ps) 必須加括號(hào)

C++指針與數(shù)組:指針詳解

C語(yǔ)言可能認(rèn)為這樣寫(xiě)太麻煩,于是對(duì)于結(jié)構(gòu)體指針我們可以使用 -> 操作符直接訪問(wèn)到結(jié)構(gòu)體的內(nèi)容:

	printf("%s\n%d\n%s\n", ps->name, ps->age, ps->sex);

ps->name 寫(xiě)法完全等價(jià)于 (*ps).name 這樣的寫(xiě)法。
注:-> 操作符只在結(jié)構(gòu)體指針變量訪問(wèn)結(jié)構(gòu)體成員時(shí)使用。

5. 多級(jí)指針

首先問(wèn)大家一個(gè)問(wèn)題,指針變量是不是變量?是變量。既然是變量,那么就有地址,我們依然可以把指針變量的地址存入一個(gè)新的變量,此變量我們可以稱為二級(jí)指針變量:

int a = 10;
int *pa = &a;
int **ppa = &pa;  // 定義二級(jí)指針變量
*ppa;  //等價(jià)于 pa
**ppa; //等價(jià)于 *pa,即等價(jià)于 a

二級(jí)指針大家不要看的多么神秘,所謂二級(jí)指針其實(shí)也就是一個(gè)指針變量,只不過(guò)里面存放的是另一個(gè)指針變量的地址而已。
既然如此,二級(jí)指針變量是不是變量呢?它能不能取地址存入另外一個(gè)三級(jí)指針變量呢?那么,三級(jí)指針變量是不是變量呢?… 如果你愿意,可以一直這么套娃下去~

6.指針變量的命名規(guī)范

之所以把這塊單獨(dú)分出來(lái)講,是因?yàn)閷?duì)指針變量進(jìn)行一個(gè)好的命名規(guī)范,不僅有利于提高代碼的可讀性,更有助于我們理解一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu)的代碼。

指針的命名習(xí)慣上在原變量名前加字母 p。 如定義整形變量 a ,其指針變量就命名為 pa, 定義結(jié)構(gòu)體變量 std 其對(duì)應(yīng)指針變量命名為 pstd,如果對(duì) pstd 再次取地址存入二級(jí)指針變量,那么該二級(jí)指針變量就應(yīng)該命名為 ppstd。

 

四. 我對(duì)指針的一些理解

都說(shuō)指針是C語(yǔ)言的靈魂,那么指針的魅力究竟在何處?

我們看這段交換兩個(gè)數(shù)的代碼:

#include <stdio.h>
void Swap(int a, int b)
{
	int t = a;
	a = b;
	b = t;
}
int main()
{
	int a = 10;
	int b = 20;
	Swap(a, b);
	printf("a = %d\n", a);
	printf("b = %d\n", b);
	return 0;
}

我們應(yīng)該知道,這段代碼是無(wú)法完成 a, b 的交換的,因?yàn)?Swap() 里的 a, b 只不過(guò)是 main() 函數(shù)里 a, b 的一份拷貝。即,Swap() 函數(shù)里 a, b 的改變是不會(huì)影響 main() 函數(shù)的。這種傳參的方式我們稱之為傳值。

可是我們這么寫(xiě):

#include <stdio.h>
void Swap(int *pa, int *pb)
{
	int t = *pa;
	*pa = *pb;
	*pb = t;
}
int main()
{
	int a = 10;
	int b = 20;
	Swap(&a, &b);
	printf("a = %d\n", a);
	printf("b = %d\n", b);
	return 0;
}

main() 傳參時(shí)傳 a, b 的地址,Swap() 函數(shù)使用指針進(jìn)行接收,內(nèi)部使用解引用方式進(jìn)行交換,我們就可以完成真正的交換功能。這種傳參的方式我們稱之為傳址。

我在一篇文章上看到這樣一個(gè)說(shuō)法,可謂是對(duì)指針理解到了本質(zhì):

  • 傳值就是傳值。
  • 傳址就是傳值本身。

值和值本身兩個(gè)概念希望大家能夠深刻理解。

如同我們 Swap() 函數(shù)的第一種寫(xiě)法,main() 函數(shù)僅僅是將 a, b 的值傳遞給了 Swap() 函數(shù)進(jìn)行處理,可無(wú)論 Swap() 函數(shù)對(duì)其做什么樣的處理,也依然無(wú)法改變?cè)瓉?lái) a, b 的值。

而 Swap() 的第二種寫(xiě)法,main() 函數(shù)傳的是 a, b 的地址,相當(dāng)于傳的是 a, b 本身,這樣 Swap() 在進(jìn)行處理時(shí)便可直接改變?cè)瓉?lái)的 a, b 的值。

 

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注服務(wù)器之家的更多內(nèi)容!

原文鏈接:https://blog.csdn.net/qq_55135139/article/details/120151642

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久精品国产一区二区电影 | 欧美精品1区2区3区 日本电影中文字幕 | 国产日产久久高清欧美一区 | 成人午夜在线 | 国产精品一区二区久久 | 国产激情在线观看 | 免费在线观看黄色av | 日韩电影网站 | 日本免费一区二区三区四区 | 国产老头老太作爱视频 | 欧美美女爱爱 | 成人日韩视频在线观看 | 久久av网站 | 91资源在线视频 | 久草中文在线观看 | 亚洲精品乱码久久久久久久久 | jizzhd中国 | 日韩在线视频一区 | 亚洲成人精品在线 | 国产精品a久久久久 | 四虎影院最新地址 | 免费看黄的视频网站 | 日韩 欧美 中文 | 国产一区二区三区撒尿在线 | 精品久| 91精品国产综合久久久久久 | 午夜欧美 | 玖玖在线播放 | 国产成人在线电影 | 欧美成人福利 | 极品女神高潮呻吟av久久 | 久久综合久久久 | 天天干夜夜操 | 成人影院在线观看 | 免费视频一区二区 | 欧美成人精品在线 | 伊人激情| 欧美国产一区二区三区 | 骚虎av| 国产高清在线a视频大全 | 黄色国产一级片 |