狠狠爱成人网_日韩一级在线_国产综合自拍_亚洲精品韩国_亚洲视频导航_麻豆成人在线播放_欧美jjzz_一区在线视频观看_美脚丝袜一区二区三区在线观看_欧美91视频

當前位置:系統之家 > 技術開發教程 > 詳細頁面

C語言之指針綜合談

C語言之指針綜合談

更新時間:2019-10-08 文章作者:未知 信息來源:網絡 閱讀次數:

  概述

  Joel Spolsky認為,對指針的理解是一種aptitude,不是通過訓練就可以達到的。雖然如此,我還是想談一談這個C/C++語言中最強勁也是最容易出錯的要素。

  鑒于指針和目前計算機內存結構的關聯,很多C語言比較本質的特點都孕育在其中,因此,本篇和第六、第七兩篇我都將以指針為主線,結合在實際編程中遇到的問題,來詳細談談關于指針的幾個重要方面。

  指針類型的本質分析

  1、指針的本質

  指針的本質:一種復合的數據類型。下面我將以下面幾個作為例子進行展開分析:

  a)、int *p;
  b)、int **p;
  c)、int (*parValue)[3];
  d)、int (*pFun)();

  分析:

  所謂的數據類型就是具有某種數據特征的東東,比如數據類型char,它的數據特征就是它所占據的內存為1個字節, 指針也很類似,指針所指向的值也占據著內存中的一塊地址,地址的長度與指針的類型有關,比如對于char型指針,這個指針占據的內存就是1個字節,因此指針也是一種數據類型,但我們知道指針本身也占據了一個內存空間地址,地址的長度和機器的字長有關,比如在32位機器中,這個長度就是4個字節,因此指針本身也同樣是一種數據類型,因此,我們說,指針其實是一種復合的數據類型,

  好了,現在我們可以分析上面的幾個例子了。

  假設有如下定義:

int nValue;

  那么,nValue的類型就是int,也就是把nValue這個具體變量去掉后剩余的部分,因此,上面的4個聲明可以類比進行分析:

  a)、int *

  *代表變量(指針本身)的值是一個地址,int代表這個地址里面存放的是一個整數,這兩個結合起來,int *定義了一個指向整數的指針,類推如下:

  b)、int **

  指向一個指向整數的指針的指針。

  c)、int (*)[3]

  指向一個擁有三個整數的數組的指針。

  d)、int (*)()

  指向一個函數的指針,這個函數參數為空,返回值為整數。

  分析結束,從上面可以看出,指針包括兩個方面,一個是它本身的值,是一個內存中的地址;另一個是指針所指向的物,是這個地址中所存放著具有各種各樣意義的數據。

  2、對指針本身值的分析

  下面例子考察指針本身的值(環境為32位的計算機):

void *p = malloc( 100 );

  請計算sizeof ( p ) = ?

char str[] = “Hello” ;
char *p = str ;

  請計算sizeof ( p ) = ?

void Func ( char str[100])
{
請計算 sizeof( str ) = ? //注意,此時,str已經退化為一個指針,詳情見
//下一篇指針與數組
}


  分析:上面的例子,答案都是4,因為從上面的討論可以知道,指針本身的值對應著內存中的一個地址,它的size只與機器的字長有關(即它是由系統的內存模型決定的),在32位機器中,這個長度是4個字節。

  3、對指針所指向物的分析

  現在再對指針這個復合類型的第二部分,指針所指向物的意義進行分析。

  上面我們已經得到了指針本身的類型,那么將指針本身的類型去掉 “*”號就可得到指針所指向物的類型,分別如下:

  a)、int

  所指向物是一個整數。

  b)、int*

  所指向物是一個指向整數的指針。

  c)、int ()[3]

  ()為空,可以去掉,變為int [3],所指向物是一個擁有三個整數的數組。

  d)、int ()()

  第一個()為空,可以去掉,變為int (),所指向物是一個函數,這個函數的參數為空,返回值為整數。

  4、附加分析

  另外,關于指針本身大小的問題,在C++中與C有所不同,這里我也順帶談一下。

  在C++中,對于指向對象成員的指針,它的大小不一定是4個字節,這主要是因為在引入多重虛擬繼承以及虛擬函數的時候,有些附加的信息也需要通過這個指針進行傳遞,因此指向對象成員的指針會增大,不論是指向成員數據,還是成員函數都是如此,具體與編譯器的實現有關,你可以編寫個很小的C++程序去驗證一下。另外,對一個類的靜態成員(static member,可以是靜態成員變量或者靜態成員函數)來說,指向它的指針只是普通的函數指針,而不是一個指向類成員的指針,所以它的大小不會增加,仍舊是4個字節。

  指針運算符&和*

  “&和*”,它們是一對相反的操作,’&’取得一個物的地址(也就是指針本身),’*’得到一個地址里放的物(指針所指向的物)。這個東西可以是值(對象)、函數、數組、類成員(class member)等等。

  參照上面的分析我們可以很好地理解&與*。

  使用指針的好處?

  關于指針的本質和基本的運算符我們討論過了,在這里,我想再籠總地談一談使用指針的必要性和好處,為我們今后的使用和對后面篇章的理解做好鋪墊。簡而言之,指針有以下好處:

  1)、方便使用動態分配的數組。

  這個解釋我放在本系列第六篇中進行講解。

  2)、對于相同類型(甚至是相似類型)的多個變量進行通用訪問。

  就是用一個指針變量不斷在多個變量之間指來指去,從而使得非常應用起來非常靈活,不過,這招也比較危險,需要小心使用:因為出現錯誤的指針是編程中非常忌諱的事情。

  3)、變相改變一個函數的值傳遞特性。

  說白了,就是指針的傳地址作用,將一個變量的地址作為參數傳給函數,這樣函數就可以修改那個變量了。

  4)、節省函數調用代價。

  我們可以將參數,尤其是大個的參數(例如結構,對象等),將他們地址作為參數傳給函數,這樣可以省去編譯器為它們制作副本所帶來的空間和時間上的開銷。

  5)、動態擴展數據結構。

  因為指針可以動態地使用malloc/new生成堆上的內存,所以在需要動態擴展數據結構的時候,非常有用;比如對于樹、鏈表、Hash表等,這幾乎是必不可少的特性。

  6)、與目前計算機的內存模型相對應,可按照內存地址進行直接存取,這使得C非常適合于一些較底層的應用。

  這也是C/C++指針一個強大的優點,我會在后面講述C語言的底層操作時,較詳細地介紹這個優點的應用。

  7)、遍歷數組。

  據個例子來說吧,當你需要對字符串數組進行操作時,想一想,你當然要用字符串指針在字符串上掃來掃去。

  …實在太多了,你可以慢慢來補充^_^。


  指針本身的相關問題

  1、問題:空指針的定義

  曾經看過有的.h文件將NULL定義為0L,為什么?

  答案與分析:

  這是一個關于空指針宏定義的問題。指針在C語言中是經常使用的,有時需要將一個指針置為空指針,例如在指針變量初始化的時候。
C語言中的空指針和Pascal或者Lisp語言中的NIL具有相同的地位。那如何定義空指針呢?下面的語句是正確的:

char *p1 = 0;
int *p2;
if (p != 0)
{
...
}
p2 = 0;


  也就是說,在指針變量的初始化、賦值、比較操作中,0會被編譯器理解為要將指針置為空指針。至于空指針的內部表示是否是0,則隨不同的機器類型而定,不過通常都是0。但是在另外一些場合下,例如函數的參數原型是指針類型,函數調用時如果將0作為參數傳入,編譯器則不能將其理解為空指針。此時需要明確的類型轉換,例如:

void func (char *p);
func ((char *)0);


  一般情況下,0是可以放在代碼中和指針關聯使用的,但是有些程序員(數量還不少呦!也許就包括你在內)不喜歡0的直白,認為其不能表示作為指針的特殊含義,于是要定義一個宏NULL,來明確表示空指針常量。這也是對的,人家C語言標準就明確說:“ NULL應該被定義為與實現相關的空指針常量”。但是將NULL定義成什么樣的值呢?我想你一定見過好幾種定義NULL的方法:

#define NULL 0
#define NULL (char *)0
#define NULL (void *)0


  在我們使用的絕大多數計算系統上,例如PC,上述定義是能夠工作的。然而,世界上還有很多其它種類的計算機,其CPU也不是Intel的。在某些系統上,指針和整數的大小和內部表示并不一致,甚至不同類型的指針的大小都不一致。為了避免這種可移植性問題,0L是一種最為安全的、最妥帖的定義方式。0L的含義是: “值為0的整數常量表達式”。這與C語言給出的空指針定義完全一致。因此,建議采用0L作為空指針常量NULL的值。

  其實 NULL定義值,和操作系統的的平臺有關, 將一個指針定義為 NULL, 其用意是為了保護操作系統,因為通過指針可以訪問任何一塊地址, 但是,有些數據是不許一般用戶訪問的,比如操作系統的核心數據。 當我們通過一個空(NULL)的指針去方位數據時,系統會提示非法, 那么系統又是如何知道的呢??

  以windows2000系統為例, 該系統規定系統中每個進程的起始地址(0x00000000)開始的某個地址范圍內是存放系統數據的,用戶進程無法訪問, 所以當用戶用空指針(0)訪問時,其實訪問的就是0x00000000地址的系統數據,由于該地址數據是受系統保護的,所以系統會提示錯誤(指針訪問非法)。

  這也就是說NULL值不一定要定義成0,起始只要定義在系統的保護范圍的地址空間內,比如定義成(0x00000001, 0x00000002)都會起到相同的作用,但是為了考慮到移植性,普遍定義為0 。

  2、問題:與指針相關的編程規則&規則分析

  指針既然這么重要,而且容易出錯,那么有沒有方法可以很好地減少這些指針相關問題的出現呢?

  答案與分析:

  減少出錯的根本是徹底理解指針。

  在方法上,遵循一定的編碼規則可能是最立竿見影的方法了,下面我來闡述一下與指針相關的編程規則:

  1) 未使用的指針初始化為NULL 。

  2) 在給指針分配空間前、分配后均應作判斷。

  3) 指針所指向的內容刪除后也要清除指針本身。

  要牢記指針是一個復合的數據結構這個本質,所以我們不論初始化和清除都要同時兼顧指針本身(上述規則1,3)和指針所指向的內容(上述規則2,3)這兩個方面。

  遵循這些規則可以有效地減少指針出錯,我們來看下面的例子:

void Test(void)
{
 char *str = (char *) malloc(100);
 strcpy(str, “hello”);
 free(str);
 if(str != NULL)
 {
  strcpy(str, “world”);
  printf(str);
 }
}


  請問運行Test函數會有什么樣的結果?

  答:

  篡改動態內存區的內容,后果難以預料,非常危險。因為free(str);之后,str成為野指針,if(str != NULL)語句不起作用。

  如果我們牢記規則3,在free(str)后增加語句:

str = NULL;


  那么,就可以防止這樣的錯誤發生。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統下載排行

狠狠爱成人网_日韩一级在线_国产综合自拍_亚洲精品韩国_亚洲视频导航_麻豆成人在线播放_欧美jjzz_一区在线视频观看_美脚丝袜一区二区三区在线观看_欧美91视频
国产一级精品在线| 欧美国产精品v| 日本一区二区三区久久久久久久久不 | 日韩欧美中文字幕制服| 中文字幕在线不卡一区二区三区 | 欧美日韩综合在线| 中文字幕乱码亚洲精品一区| 天天亚洲美女在线视频| 99国产精品视频免费观看| 免费中文字幕日韩欧美| 日韩精品一区在线| 午夜精品久久一牛影视| 色综合天天综合| 欧美色图天堂网| 最新国产成人在线观看| 国产精品一区二区不卡| 国产一区91| 日本一区二区免费在线| 韩国女主播一区二区三区| 91久久综合| 久久久久久免费毛片精品| 久久精品国产**网站演员| 最新亚洲视频| 久久久久久久久久久久久夜| 毛片基地黄久久久久久天堂| 亚洲毛片av| 久久久久久亚洲综合影院红桃| 蜜臀av国产精品久久久久| 亚洲毛片av| 中文字幕欧美区| 成人免费va视频| 欧美视频一区二| 性做久久久久久| 亚洲动漫精品| 久久久久综合网| 成人av电影免费在线播放| 日韩精品专区在线| 蜜臀a∨国产成人精品| 先锋a资源在线看亚洲| 国产精品久久久久9999吃药| 国产成人精品www牛牛影视| 色女孩综合影院| 亚洲综合小说图片| 一本色道久久综合亚洲精品不卡| 国产亚洲成年网址在线观看| 国产福利91精品一区| 欧美午夜精品电影| 日本不卡不码高清免费观看| 亚洲影视在线| 亚洲二区在线观看| 小嫩嫩精品导航| 午夜精品久久久久久| 亚洲一区二区三区四区五区午夜| 亚洲欧美在线视频观看| 欧美三级午夜理伦三级中文幕| 精品国产三级电影在线观看| 国产福利一区二区三区在线视频| 欧美精品一二三区| 久久国产精品99久久久久久老狼 | 国产一区二区三区日韩| 欧美精品精品一区| 国产一区二区三区综合| 日韩欧美一区二区不卡| 成人高清视频在线| 久久久久88色偷偷免费| 欧美日韩国产一区精品一区| 国产精品伦理在线| 亚洲韩日在线| 亚洲精品视频在线观看网站| 99国产精品久久久久久久成人热| 一区二区三区高清在线| 免费一区视频| 麻豆精品蜜桃视频网站| 91麻豆精品久久久久蜜臀| 国产精品一品视频| 久久久久久久综合狠狠综合| 欧美黄免费看| 亚洲乱码国产乱码精品精可以看| 国产精品久久国产三级国电话系列| 亚洲香肠在线观看| 在线观看视频一区二区| 国产精品资源在线观看| 久久精品夜夜夜夜久久| 中文在线一区| 九九精品一区二区| 精品理论电影在线| 影音先锋亚洲精品| 亚洲 欧美综合在线网络| 欧美美女视频在线观看| av电影天堂一区二区在线观看| 国产精品每日更新| 久久激情久久| 国产成人鲁色资源国产91色综| 久久久久久久久久久久久女国产乱 | 国产欧美一区在线| 国产精品一二| 国产精品一二一区| 中文字幕中文乱码欧美一区二区| 久久国产精品亚洲77777| 国产精品911| 综合在线观看色| 欧美性生活久久| 欧美高清视频一区| 日韩电影在线观看电影| 日韩女优制服丝袜电影| 91久久精品www人人做人人爽| 美女精品自拍一二三四| 国产欧美一区二区三区网站 | 国产超碰在线一区| 亚洲精品精品亚洲| 日韩午夜av电影| 一本色道久久99精品综合| 国产成人精品免费看| 亚洲一区二区精品久久av| 日韩欧美亚洲国产精品字幕久久久| 亚洲第一在线| 成人久久18免费网站麻豆| 欧美一区成人| 亚洲444eee在线观看| 日韩欧美一二区| 91精品91久久久中77777| 牛牛国产精品| 久久99精品久久久| 一区二区三区四区不卡视频| 欧美一区二区三区婷婷月色| 国产精品美女xx| 99精品热视频| 激情丁香综合五月| 亚洲一区在线视频| 中国色在线观看另类| 欧美日韩1区2区| 亚洲伊人网站| 在线电影一区| 91麻豆产精品久久久久久| 精品影视av免费| 亚洲综合在线免费观看| 久久免费精品国产久精品久久久久 | 亚洲视频一区在线观看| 精品国产a毛片| 欧美久久久久久久久| 久久一区二区三区超碰国产精品| 欧美日韩一区二区三| 高清久久久久久| 激情图片小说一区| 日本视频一区二区三区| 亚洲愉拍自拍另类高清精品| 国产精品久久久久久亚洲毛片 | 亚洲黄色成人久久久| 欧美日韩国产三区| 97精品久久久午夜一区二区三区| 国产精品影视网| 久久不见久久见免费视频1| 亚洲成a人v欧美综合天堂下载 | 在线日韩一区二区| 久久综合九色99| 久久在线91| 性伦欧美刺激片在线观看| 夜夜嗨一区二区| 一区二区三区四区五区精品| 一区在线免费| 亚洲国产二区| 黄色亚洲大片免费在线观看| 欧美天堂亚洲电影院在线观看| 99久久久无码国产精品| 99riav一区二区三区| 91亚洲精品久久久蜜桃网站 | 亚洲午夜av在线| 亚洲国产精品尤物yw在线观看| 一区二区三区精品在线观看| 亚洲黄色免费电影| 亚洲国产视频在线| 亚洲成av人片一区二区梦乃 | 91精品久久久久久蜜臀| 欧美一区二区在线免费观看| 91精选在线观看| 欧美mv日韩mv国产| 久久精品视频一区二区三区| 久久久久国产成人精品亚洲午夜| 久久久久综合网| 一区在线播放视频| 亚洲一区二区五区| 日韩高清在线电影| 精品一区二区在线播放| 高清国产一区二区| 91天堂素人约啪| 激情综合电影网| 久久久久综合| 7777精品伊人久久久大香线蕉 | 久久天堂国产精品| 欧美日韩在线播放三区| 精品三级在线观看| 一区免费观看视频| 亚洲v日本v欧美v久久精品| 久久精品国产免费| av中文字幕不卡| 亚洲黑丝一区二区| 亚洲图片欧美综合| 首页综合国产亚洲丝袜| 韩国欧美国产1区| 欧美日韩精品综合|