亚洲一级免费看,特黄特色大片免费观看播放器,777毛片,久久久久国产一区二区三区四区,欧美三级一区二区,国产精品一区二区久久久久,人人澡人人草

C語(yǔ)言

C語(yǔ)言中的指針解讀

時(shí)間:2025-04-08 01:25:17 C語(yǔ)言 我要投稿
  • 相關(guān)推薦

C語(yǔ)言中的指針解讀

指針無(wú)疑是一個(gè)難點(diǎn)。但是,我覺(jué)得指針也是C語(yǔ)言特別重要的一個(gè)特性。也許,你在除了C和C++以外的編程語(yǔ)言中,很少看到指針。而C++中,也多用引用,而非指針。指針,作為一種高效的工具,可謂是一把雙刃劍——用得好,可以大大提高程序效率,但用的不好,就是很多bug的滋生地。下面是指針相關(guān)的知識(shí),歡迎閱讀。

  這或許也是人們對(duì)指針褒貶不一的原因吧。就我個(gè)人而言,我還是很喜歡這個(gè)特性,因?yàn)槲倚枰?jīng)常和硬件以及一些底層的軟件打交道。這個(gè)時(shí)候,指針便體現(xiàn)出它獨(dú)特的魅力。指針的知識(shí)很多,有一本經(jīng)典的書(shū)叫《C和指針》,如果有興趣可以讀一讀。這里,我主要總結(jié)一些如何去解讀指針(說(shuō)實(shí)話(huà)這個(gè)東西實(shí)在是很容易讓人困惑)的方法,一方面給自己做查詢(xún)用,另一方面,希望可以給別人一些幫助。

  一,基本概念

  關(guān)于指針的基本概念,我就不詳細(xì)介紹了,因?yàn)橛性S多書(shū)都介紹的很詳細(xì)。這里我只介紹一部分。指針指向一個(gè)地址,而指針本身在大多數(shù)系統(tǒng)上都是一個(gè)無(wú)符號(hào)整數(shù)(在32bit機(jī)上是4byte,在64bit機(jī)上是8byte)。下面用一個(gè)例子來(lái)說(shuō)明其機(jī)制:

  在上面的例子中,先定義了一個(gè)指針p,它的類(lèi)型是int,也就是說(shuō)它只能指向一個(gè)int型的變量,而不能指向其他類(lèi)型的變量。最后我們將a變量的地址賦給p。在這個(gè)過(guò)程中,涉及到兩個(gè)內(nèi)存塊,一個(gè)是存放指針p的內(nèi)存(用&p可得到內(nèi)存地址),一個(gè)是存放a的值的`內(nèi)存塊(用&a可以得到內(nèi)存地址)。而第一個(gè)內(nèi)存存的p的值經(jīng)過(guò)賦值語(yǔ)句后也就是&a的值了。另外一個(gè)注意點(diǎn)是, *(星號(hào))和變量類(lèi)型以及變量名之間可以有任意個(gè)空格,也可以沒(méi)有。比如下面三種方式都是一樣的:

  int a = 10;

  int *p; //聲明一個(gè)指針,但未初始化,此時(shí)為野指針

  p = &a; //將a變量的地址賦給指針p

  在上面的例子中,先定義了一個(gè)指針p,它的類(lèi)型是int,也就是說(shuō)它只能指向一個(gè)int型的變量,而不能指向其他類(lèi)型的變量。最后我們將a變量的地址賦給p。在這個(gè)過(guò)程中,涉及到兩個(gè)內(nèi)存塊,一個(gè)是存放指針p的內(nèi)存(用&p可得到內(nèi)存地址),一個(gè)是存放a的值的內(nèi)存塊(用&a可以得到內(nèi)存地址)。而第一個(gè)內(nèi)存存的p的值經(jīng)過(guò)賦值語(yǔ)句后也就是&a的值了。另外一個(gè)注意點(diǎn)是, *(星號(hào))和變量類(lèi)型以及變量名之間可以有任意個(gè)空格,也可以沒(méi)有。比如下面三種方式都是一樣的:

  int* a;

  int * a;

  int *a;

  解讀方法:

  首先從標(biāo)示符開(kāi)始閱讀,然后往右讀,每遇到圓括號(hào)的右半邊就調(diào)轉(zhuǎn)閱讀方向。重復(fù)這個(gè)過(guò)程直到整個(gè)聲明解析完畢。需要注意的是,已經(jīng)讀過(guò)的部分在后續(xù)作為一個(gè)整體來(lái)看。

  看下面一個(gè)例子:

  int *a[3];

  //首先a右邊是[],說(shuō)明a是一個(gè)具有3個(gè)元素的數(shù)組

  //右邊讀完,則讀左邊。a左邊是int*,說(shuō)明a的元素是int類(lèi)型的指針

  int (*a)[3]

  //首先,a右邊是圓括號(hào)的右半邊,轉(zhuǎn)向,左邊是一個(gè)*,說(shuō)明a是一個(gè)指針

  //遇到括號(hào),再轉(zhuǎn)向,是一個(gè)[],說(shuō)明a是一個(gè)指向3個(gè)元素的數(shù)組的指針

  //左邊是int,說(shuō)明元素類(lèi)型是int

  //所以,a是一個(gè)指向具有3個(gè)整型元素的數(shù)組的指針

  int (*func)(int p);

  //相同的方法,func首先是一個(gè)指針

  //然后右邊是一個(gè)括號(hào),說(shuō)明(func)是個(gè)函數(shù),而func是指向這個(gè)函數(shù)的指針

  //這個(gè)函數(shù)具有int類(lèi)型的參數(shù),返回值類(lèi)型為int

  int (*func[3])(int p);

  //同理,func首先是一個(gè)具有3個(gè)元素的數(shù)組

  //其次,func左邊是一個(gè)*,說(shuō)明func數(shù)組的元素是指針。要注意修飾的是func[3],而不是func。因?yàn)橐呀?jīng)讀過(guò)的部分在后面都作為一個(gè)整體來(lái)對(duì)待

  //跳出第一個(gè)圓括號(hào),右邊又是一個(gè)圓括號(hào),說(shuō)明func數(shù)組的元素是函數(shù)類(lèi)型的指針。這個(gè)函數(shù)具有int類(lèi)型的參數(shù)和int型返回值

  二,數(shù)組首地址a,&a,&a[0]

  注:a,&a,&a[0]的含義雖然不同,但是他們?nèi)齻(gè)的值是相等的!

  以int a[3]為例說(shuō)明:

  a作為右值時(shí),代表數(shù)組首元素的首地址,而非數(shù)組地址。 也就是a[0]的地址。int i = (a+1),這里a是右值,所以代表首元素的首地址,a+1代表下一個(gè)元素的首地址,即&a[1]。

  a是整個(gè)數(shù)組的名字。所以sizeof(a)的值為sizeof(int) * 3 = 40,代表整個(gè)數(shù)組的大小。

  &a即為取a的首地址,也即整個(gè)數(shù)組的首地址。所以sizeof(&a) = 4。 int p = (int)(&a+1)中的&a+1代表下一個(gè)數(shù)組的首地址,顯然是越界的。

  &a[0]代表首元素的首地址。 所以sizeof(&a[0]) = 4。

  &a[3],很顯然數(shù)組越界了,但它的sizeof是多少呢? 也是4,因?yàn)殛P(guān)鍵字sizeof求值是在編譯的時(shí)候,雖然并不存在a[3]這個(gè)元素,但是這里并沒(méi)有真正訪問(wèn)a[3],而是根據(jù)數(shù)組元素類(lèi)型來(lái)確定其值的。所以sizeof(a[3])不會(huì)出錯(cuò)。

  a[-1]代表什么意思?首先要明白下標(biāo)的形式被編譯器解析成指針的形式,即a[1]被解析成(a+1)。那么,a[-1]被解析成*(a-1)。

  關(guān)于數(shù)組首元素的首地址和數(shù)組的首地址的區(qū)別:其實(shí),數(shù)組首元素的首地址和數(shù)組首地址的值是相同的,即&a[0]和a(以及&a)是相等的,但是而這含義不一樣。首元素的首地址加1后,是第二個(gè)元素的.首地址(之所以一直說(shuō)首地址,是因?yàn)橛械念?lèi)型存儲(chǔ)時(shí)會(huì)占多個(gè)地址),但數(shù)組的首地址加1后是“下一個(gè)數(shù)組的地址”,這里的下一個(gè)數(shù)組只是為了說(shuō)明加1時(shí)加了整個(gè)數(shù)組的大小,而不是一個(gè)元素的大小。

  有一點(diǎn)比較容易混淆:a雖然代表整個(gè)數(shù)組,但(a+1)卻代表下一個(gè)元素的首地址,即和(&a[0]+1)一樣,下一個(gè)數(shù)組的形式為:(&a+1)。 下面以一個(gè)程序來(lái)說(shuō)明:

  #include

  int main()

  {

  int a[3] = {1, 2, 3};

  printf("%ld ",sizeof(long unsigned int));

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

  printf("sizeof(a)=%ld ", sizeof(a));

  printf("sizeof(&a[3])=%ld ", sizeof(&a[3]));

  printf("a[-1]=%d *(a-1)=%d ",a[-1],*(a-1));

  printf("a=%p &a=%p &a[0]=%p ",a, &a,&a[0]);

  printf("a=%p (a+1)=%p (&a+1)=%p ",a,(a+1),(&a+1));

  return 0;

  }

  輸出結(jié)果:

  8

  *(a+1)=2

  sizeof(a)=12

  sizeof(&a[3])=8

  a[-1]=0 *(a-1)=0

  a=0x7fffcb4cb980 &a=0x7fffcb4cb980 &a[0]=0x7fffcb4cb980

  a=0x7fffcb4cb980 (a+1)=0x7fffcb4cb984 (&a+1)=0x7fffcb4cb98c

  說(shuō)明(下面的行數(shù)只計(jì)算main函數(shù)內(nèi)有代碼的行):

  程序第1行定義了一個(gè)具有3個(gè)元素的整型數(shù)組。

  第2行打印了long型的大小。因?yàn)槲沂?4bit的,所以一個(gè)long是8byte。

  第3行打印了*(a+1)的值,結(jié)果和a[1]的值相等。說(shuō)明a雖然代表整個(gè)數(shù)組,但作為右值時(shí),的確代表首元素的首地址。

  第4行輸出值為12,是整個(gè)數(shù)組的大小。

  第5行打印了一個(gè)出界元素的大小,沒(méi)有報(bào)錯(cuò),驗(yàn)證了上面第5條。

  第6行打印了a[-1]和*(a-1),輸出值相等。驗(yàn)證了上面第6條。

  第7行打印了a和&a[0],值相等。說(shuō)明數(shù)組的首地址和首元素的首地址是相等的。

  第8行打印了a,(a+1),(&a+1),由結(jié)果就可以看出首元素的首地址加1是加了一個(gè)數(shù)組元素的大小,而數(shù)組首地址加1是加了一個(gè)數(shù)組的大小。

  三,指針數(shù)組和數(shù)組指針

  指針數(shù)組: 首先它是一個(gè)數(shù)組,數(shù)組的元素是指針,也成為“存儲(chǔ)指針的`數(shù)組”。

  數(shù)組指針: 首先它是一個(gè)指針,它指向一個(gè)數(shù)組,也可以理解為“數(shù)組的指針”。 也可以利用前面的“解讀方法”去分析。

  四,函數(shù)指針和指針函數(shù)

  函數(shù)指針: 指向函數(shù)的指針變量。

  指針函數(shù): 帶指針的函數(shù),也就是返回指針的函數(shù)。

  char * fun(char* a, char* b) //定義為指針函數(shù)

  {

  ...

  ...

  }

  int main()

  {

  char* (*p)(char* p1, char* p2); //定義函數(shù)指針

  p = &fun; //把函數(shù)地址賦給它

  //p = fun; //這樣寫(xiě)也行

  (*p)("aa", "bb"); //使用函數(shù)指針

  return 0;

  }

  四,指針常量和常量指針

  const char* p1; //常量指針,指向常量的指針

  char const* p2; //同上

  char* const p3; //指針常量,指針是常量

  怎么記?

  可以先把類(lèi)型名去掉,然后看const離誰(shuí)近,就修飾誰(shuí)。

  也可以const在*左邊的為常量指針,const在*右邊的.為指針常量。

  五、萬(wàn)x鑰匙

  其實(shí),關(guān)于“指針數(shù)組與數(shù)組指針、函數(shù)指針與指針函數(shù)、指針常量與常量指針”的判斷,有一個(gè)萬(wàn)能x匙。那就是根據(jù)我們強(qiáng)大的.中文語(yǔ)法:前邊是修飾詞,后邊才是主語(yǔ)。比如“指針數(shù)組”,前面的指針只是修飾詞,后面的數(shù)組才是主語(yǔ),所以它是一個(gè)數(shù)組。

  六,野指針

  野指針指沒(méi)有確定指向的指針。造成野指針的情況有:

  1. 指針變量創(chuàng)建但沒(méi)有初始化。

  2. 指針p被free或者之后,沒(méi)有置為NULL。


【 C語(yǔ)言中的指針解讀】相關(guān)文章:

什么是C語(yǔ)言中指針 C語(yǔ)言指針的基礎(chǔ)使用10-01

C語(yǔ)言中指針的概念03-16

C語(yǔ)言中的指針是什么08-08

C語(yǔ)言中的指針指什么08-23

C語(yǔ)言中野指針的深入解析08-06

C語(yǔ)言中指針與數(shù)組的區(qū)別10-09

C語(yǔ)言中的指針和內(nèi)存泄漏08-07

C語(yǔ)言中指針的用法介紹10-27

C語(yǔ)言中指針函數(shù)與函數(shù)指針有何區(qū)別09-28