成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【C語(yǔ)言】指針篇——你必須要掌握的指針基礎(chǔ)知識(shí)

番茄西紅柿 / 3477人閱讀

摘要:一指針概述指針是個(gè)變量存放內(nèi)存單元的地址編號(hào)。即存放指針變量的地址的指針二級(jí)指針指向的空間的值是一個(gè)一級(jí)指針??偨Y(jié)指針是語(yǔ)言非常重要的一部分內(nèi)容繁多不易懂本文僅介紹了一些基本知識(shí)后續(xù)還會(huì)深入了解指針。


前言

指針是C語(yǔ)言的重點(diǎn)和難點(diǎn),熟練的掌握指針能夠更好的理解計(jì)算的存儲(chǔ)方式,同時(shí)簡(jiǎn)化代碼,增強(qiáng)程序的效率。

一、指針概述

指針是個(gè)變量,存放內(nèi)存單元的地址(編號(hào))。

指針的創(chuàng)建

在定義指針變量的時(shí)候,在變量前面加上’ * ',代表這個(gè)變量是一個(gè)指針,再往前面加上一個(gè)類型名,就代表指針的類型,稱為XX指針。

指針的初始化:

  • 使用&(取地址操作符)可以獲得變量的地址,將其賦值給已經(jīng)定義好的指針變量,需要它們的類型相同,類型不同的時(shí)候可以使用強(qiáng)制轉(zhuǎn)換。
  • 如果暫時(shí)不知道需要存放什么地址的時(shí)候,可以先讓它指向NULL((void*)0),NULL本質(zhì)就是0,0這個(gè)地址是不允許存儲(chǔ)的。
#include int main(){	int a = 10;//在內(nèi)存中開(kāi)辟一塊空間	int *p = &a;//這里我們對(duì)變量a,取出它的地址,可以使用&操作符。				//將a的地址存放在p變量中,p就是一個(gè)指針變量。	return 0;}

指針的大小

指針可以是不同的類型,char*、int*、float*、double*、long*等我們熟知的類型,那指針在內(nèi)存中占多大的空間呢?

對(duì)于32位的機(jī)器,假設(shè)有32根地址線,那么假設(shè)每根地址線在尋址的是產(chǎn)生一個(gè)電信號(hào)正電/負(fù)電(1或者0)
那么32根地址線產(chǎn)生的地址就會(huì)是:

00000000 00000000 00000000 00000000
……
111111111 111111111 111111111 111111111
共有232個(gè)地址,每一個(gè)地址能指向一個(gè)內(nèi)存單元(一字節(jié)),那么有232個(gè)內(nèi)存單元。

我們知道一個(gè)內(nèi)存單元的大小為一字節(jié),一根地址線是32位01組成的,那么要存放指針(地址),也就需要32個(gè)bit,也即4字節(jié)。所以在32位平臺(tái)下不論是什么類型的指針都是4個(gè)字節(jié)。

同理,在64位平臺(tái)下有64根地址線,每個(gè)地址是64位,所以需要8個(gè)字節(jié)。

如何使用指針

使用’ * '操作符對(duì)指針進(jìn)行解引用,可以獲取到指針指向空間的值
我們來(lái)運(yùn)行下方代碼。

#include int main(){	int n = 0x11223344;	char* pc = (char*)&n;//將n的地址(指針)強(qiáng)制轉(zhuǎn)換成char* 類型	int* pi = &n;	*pc = 0;//改變它指向空間的值	*pi = 0;	return 0;}

我們開(kāi)始調(diào)試代碼,查看n的內(nèi)存,最左邊是地址,右邊是以16進(jìn)制顯示內(nèi)存里存放的數(shù)據(jù),而n也是以16進(jìn)制存進(jìn)去的,兩個(gè)16進(jìn)制代表一個(gè)字節(jié),如下圖:

當(dāng)執(zhí)行完語(yǔ)句 *pc=0;

因?yàn)閜c指向的是char* 類型,只能訪問(wèn)一個(gè)字節(jié),所以只能修改一個(gè)字節(jié)。
再執(zhí)行*pi = 0;

此時(shí)n的內(nèi)存數(shù)據(jù)全部變成了0,說(shuō)明int*類型的指針可以訪問(wèn)4個(gè)字節(jié)。

總結(jié):
指針的類型決定了,對(duì)指針解引用的時(shí)候有多大的權(quán)限(能操作幾個(gè)節(jié))。 比如: char* 的指針解引用就只能訪問(wèn)一個(gè)字節(jié),而 int* 的指針的解引用就能訪問(wèn)四個(gè)字節(jié)。

二級(jí)指針

指針變量也是變量,是變量就有地址,那指針變量的地址存放在哪里? 這就是 二級(jí)指針
即存放指針變量的地址的指針,二級(jí)指針指向的空間的值是一個(gè)一級(jí)指針。

int main(){	int a = 20;	int* p = &a;	int** pp = &p;	printf("%d/n", *p);//解引用即可拿到指針指向空間里面的值	printf("%d/n", *p); //對(duì)二級(jí)指針,需要兩次解引用才能拿到最開(kāi)始的值	return 0;}


二、野指針

野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的、沒(méi)有明確限制的)。

形成野指針的原因

  1. 指針未初始化
#include int main(){	int *p;//局部變量指針未初始化,默認(rèn)為隨機(jī)值	*p = 20;//往一個(gè)隨機(jī)的地址(不屬于本程序的空間)里面放入數(shù)據(jù),是不允許的	return 0;}
  1. 指針越界訪問(wèn)
    指針想要訪問(wèn)不屬于本程序的空間,造成越界訪問(wèn),程序出錯(cuò),在使用數(shù)組的時(shí)候最容易發(fā)生。
#include int main(){	int arr[10] = {0};	int *p = arr;	int i = 0;    for(i=0; i<=11; i++)	{  		//當(dāng)指針指向的范圍超出數(shù)組arr的范圍時(shí),p就是野指針    	*(p++) = i;	}	return 0;}
  1. 指針指向的空間釋放
    當(dāng)動(dòng)態(tài)開(kāi)辟的內(nèi)存被釋放后,此時(shí)的指針就屬于野指針,它指向的位置它不能正常訪問(wèn)。關(guān)于動(dòng)態(tài)內(nèi)存分配,后續(xù)會(huì)細(xì)講。
int main(){	//開(kāi)辟一個(gè)整形空間	int* p = (int*)malloc(sizeof(int));	//釋放該空間	free(p);	//此時(shí)p即為野指針,因?yàn)樗赶虻目臻g已經(jīng)無(wú)法訪問(wèn),一般需要將其置空	//將其指向空指針,防止后續(xù)調(diào)用出錯(cuò)	p = NULL;	return 0;}

如何規(guī)避野指針

  • 指針初始化
  • 小心指針越界
  • 指針指向空間釋放即使置NULL
  • 指針使用之前檢查有效性

三、指針的基本運(yùn)算

關(guān)于指針的運(yùn)算一般有兩個(gè),指針+指針,語(yǔ)義是合法,但沒(méi)有意義。

  • 指針± 整數(shù)
  • 指針-指針

指針± 整數(shù)

對(duì)int和char類型的指針?lè)謩e進(jìn)行+1操作,%p以16進(jìn)制打印

int main(){	int n = 10;	char* pc = (char*)&n;//將n的地址(指針)強(qiáng)制轉(zhuǎn)換成char* 類型	int* pi = &n;	printf("&n:    %p/n", &n);	printf("pc:    %p/n", pc);	printf("pc + 1:%p/n", pc + 1);	printf("pi:    %p/n", pi);	printf("pi + 1:%p/n", pi + 1);	return 0;}


總結(jié):
指針的類型決定了指針向前或者向后走一步有多大(距離)。

指針-指針

int main(){	int arr[10] = { 0 };	//取出數(shù)組第一個(gè)元素和最后一個(gè)元素的地址	int* start = arr;	int* end = &arr[9];	printf("%d/n", end - start);	return 0;}


總結(jié):
指針-指針等于它們之間相差的類型數(shù)據(jù)的個(gè)數(shù)。即本例的第10個(gè)元素和第1個(gè)元素之間相差9。

四、指針和數(shù)組

一起來(lái)看一下數(shù)組名是什么

#include int main(){	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };	printf("%p/n", arr);	printf("%p/n", &arr[0]);	return 0;}


可見(jiàn)數(shù)組名和數(shù)組首元素的地址是一樣的。

結(jié)論: 數(shù)組名表示的是數(shù)組首元素的地址。也是一個(gè)指針

那么我們就可以用一個(gè)指針來(lái)代替數(shù)組名,如下代碼:

int main(){	int arr[10] = { 0 };	int* p = arr;	int i = 0;	int sz = sizeof(arr) / sizeof(arr[0]);//計(jì)算數(shù)組元素個(gè)數(shù)	//對(duì)數(shù)組賦值	for (i = 0; i < sz; i++)	{		*(p + i) = i;	}	//打印數(shù)組數(shù)據(jù)	for (i = 0; i < sz; i++)	{		printf("%d ", *(p + i));	}	return 0;}


注意:
數(shù)組名在下面兩種情況下不是首元素的地址

  1. sizeof(數(shù)組名) - 這里的數(shù)組名不是首元素的地址,是表示整個(gè)數(shù)組的,這里計(jì)算的是整個(gè)數(shù)組的大小,單位還是字節(jié)
  2. &數(shù)組名 - 這里的數(shù)組名不是首元素的地址,是表示整個(gè)數(shù)組的,拿到的是整個(gè)數(shù)組的地址
int main(){	int arr[10] = { 0 };	int sz = sizeof(arr);	printf("sizeof(arr)計(jì)算的是整個(gè)數(shù)組的大小:%d/n", sz);	printf("數(shù)組首地址:      %p/n", arr);	printf("數(shù)組首元素地址:  %p/n", &arr[0]);	printf("數(shù)組的地址:      %p/n", &arr);	printf("數(shù)組首地址+1:    %p/n", arr + 1);	printf("數(shù)組首元素地址+1:%p/n", &arr[0] + 1);	printf("數(shù)組的地址+1:    %p/n", &arr + 1);	//數(shù)組名確實(shí)是首元素的地址	//但是有2個(gè)例外:	//1. sizeof(數(shù)組名)  - 這里的數(shù)組名不是首元素的地址,是表示整個(gè)數(shù)組的,這里計(jì)算的是整個(gè)數(shù)組的大小,單位還是字節(jié)	//2. &數(shù)組名 - 這里的數(shù)組名不是首元素的地址,是表示整個(gè)數(shù)組的,拿到的是整個(gè)數(shù)組的地址	//	return 0;}

五、指針數(shù)組

存放指針的數(shù)組。

int main(){	int a = 1;	int b = 2;	int c = 3;	int* arr[10] = { &a,&b,&c };	for (int i = 0; i < 3 ; i++)	{		printf("%d ", *(arr[i]));	}	return 0;}


總結(jié)

指針是C語(yǔ)言非常重要的一部分,內(nèi)容繁多不易懂,本文僅介紹了一些基本知識(shí),后續(xù)還會(huì)深入了解指針。

希望能對(duì)大家學(xué)習(xí)指針有所幫助!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/121276.html

相關(guān)文章

  • 白話Java I/O模型

    摘要:因?yàn)樗械臄?shù)據(jù)從最底層講是字節(jié),那么就可以使用字節(jié)流這個(gè)概念去指代數(shù)據(jù)動(dòng)態(tài)轉(zhuǎn)移這個(gè)過(guò)程。而數(shù)據(jù)的轉(zhuǎn)移,就是把一堆字節(jié)流從運(yùn)往。創(chuàng)建內(nèi)存中的中轉(zhuǎn)區(qū)域,然后將上面的文件的字節(jié)流直接接入到這個(gè)。然后再?gòu)陌炎止?jié)流輸出到對(duì)應(yīng)的。 I/O的很多操作和使用,其實(shí)并不是一個(gè)非常直觀的概念,特別是打開(kāi)文件、創(chuàng)建buffer。這對(duì)于終端用戶來(lái)講是個(gè)非常奇葩和奇怪的過(guò)程。我只是想要從一個(gè)文件里讀取內(nèi)容,從過(guò)...

    VincentFF 評(píng)論0 收藏0
  • 開(kāi)學(xué)了,計(jì)算機(jī)大學(xué)生們,送你們一經(jīng)書(shū),希望你們四年不負(fù)年華!

    摘要:作為十幾年的老開(kāi)發(fā)者,今天我來(lái)分享一下,我個(gè)人認(rèn)為的大學(xué)計(jì)算機(jī)相關(guān)專業(yè)該怎么學(xué),希望你們的四年能夠不負(fù)年華。粉絲專屬福利九關(guān)于考研有能力去考研的,我建議去嘗試一下考研,理由有以下幾點(diǎn)第一,畢業(yè)就工作的人,前三年還處于摸索和定性的階段。 ...

    duan199226 評(píng)論0 收藏0
  • 從小白程序員一路晉升為大廠高級(jí)技術(shù)專家我看過(guò)哪些書(shū)籍?(建議收藏)

    摘要:大家好,我是冰河有句話叫做投資啥都不如投資自己的回報(bào)率高。馬上就十一國(guó)慶假期了,給小伙伴們分享下,從小白程序員到大廠高級(jí)技術(shù)專家我看過(guò)哪些技術(shù)類書(shū)籍。 大家好,我是...

    sf_wangchong 評(píng)論0 收藏0
  • 開(kāi)始學(xué)習(xí)機(jī)器學(xué)習(xí)之前你必須要了解知識(shí)有哪些?機(jī)器學(xué)習(xí)系列入門(mén)

    摘要:進(jìn)入當(dāng)前程序的學(xué)習(xí)系統(tǒng)的所有樣本稱作輸入,并組成輸入空間。結(jié)束語(yǔ)注意這篇文章僅僅是我接下來(lái)的機(jī)器學(xué)習(xí)系列的第一篇,后續(xù)還會(huì)有更多的內(nèi)容。 往期回顧:統(tǒng)計(jì)學(xué)習(xí)方法第...

    leoperfect 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<