• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

      淺談C語(yǔ)言中指針的理解及應(yīng)用

      2017-06-06 12:30:10曾凡舒
      廣東教育·職教版 2017年5期
      關(guān)鍵詞:運(yùn)算符存儲(chǔ)單元數(shù)組

      曾凡舒

      指針是C語(yǔ)言中一種廣泛使用的數(shù)據(jù)類型,也是C語(yǔ)言的重要特性。在C語(yǔ)言中,使用指針能夠編寫出高效、精煉、簡(jiǎn)潔的程序代碼。因此,在C語(yǔ)言的學(xué)習(xí)過(guò)程中,能否正確理解和使用指針是檢驗(yàn)是否掌握C語(yǔ)言的一個(gè)重要標(biāo)志,但是,指針也是C語(yǔ)言中最為困難的部分之一。指針的學(xué)習(xí)像其他內(nèi)容一樣也必須從理解基本概念開始。

      一、計(jì)算機(jī)基本原理

      半個(gè)多世紀(jì)以來(lái),雖然計(jì)算機(jī)制造技術(shù)發(fā)生了巨大變化,但仍然沿用馮·諾依曼體系結(jié)構(gòu)。在馮·諾依曼計(jì)算機(jī)體系結(jié)構(gòu)理論中,有三個(gè)基本思想:1)計(jì)算機(jī)處理的數(shù)據(jù)和指令采均用二進(jìn)制數(shù)表示;2)計(jì)算機(jī)運(yùn)行過(guò)程中,指令和數(shù)據(jù)首先存入主存儲(chǔ)器(內(nèi)存),計(jì)算機(jī)將自動(dòng)地并按順序從主存儲(chǔ)器中取出指令一條一條地執(zhí)行,這一概念稱作順序存儲(chǔ)程序;3)計(jì)算機(jī)硬件由運(yùn)算器、控制器、存儲(chǔ)器、輸入設(shè)備和輸出設(shè)備五大部分組成。

      計(jì)算機(jī)的主存儲(chǔ)器是由一系列連續(xù)編號(hào)或編碼的存儲(chǔ)單元組成,要運(yùn)行的程序指令以及相關(guān)的數(shù)據(jù)都按照一定的順序存儲(chǔ)在內(nèi)存中,如圖1所示。存儲(chǔ)單元中存儲(chǔ)的內(nèi)容有三種:1)指令,如0x03000、0x03001存儲(chǔ)單元,2)直接數(shù)據(jù),如0x05027、0x05028、0x05029、0x05030存儲(chǔ)單元,3)地址數(shù)據(jù),如0x03002、0x03003存儲(chǔ)單元,它們存儲(chǔ)的是存儲(chǔ)單元0x05030、0x05027的地址值。

      二、指針的基本概念

      C語(yǔ)言的設(shè)計(jì)者Brian W.Kernighan在《C程序設(shè)計(jì)語(yǔ)言》一書中給指針的定義是:指針是一種保存變量地址的變量,因此要真確理解指針概念,先要理解幾個(gè)指針相關(guān)的概念,如地址、變量等。

      地址:在計(jì)算機(jī)中,通過(guò)尋址機(jī)構(gòu)將物理存儲(chǔ)介質(zhì)映射成一維線性空間,并以字節(jié)為單位進(jìn)行統(tǒng)一編碼,使得每個(gè)字節(jié)都具有唯一的編碼,類似于街道的門牌號(hào)碼,該編碼稱為字節(jié)的地址,也稱內(nèi)存地址。內(nèi)存地址采用無(wú)符號(hào)整數(shù)來(lái)表示,例如在32位計(jì)算機(jī)中,內(nèi)存地址編碼為0x00000000 ~0xFFFFFFFF,能夠支持最大4GB的內(nèi)存空間,每個(gè)字節(jié)的地址采用32位的無(wú)符號(hào)整數(shù)表示。

      存儲(chǔ)單元:在計(jì)算機(jī)系統(tǒng)中,絕大多數(shù)的數(shù)據(jù)往往需要多個(gè)字節(jié)來(lái)存儲(chǔ),如Unicode字符、整數(shù)、浮點(diǎn)小數(shù)、字符串等。所以,需要分配一個(gè)或連續(xù)的多個(gè)字節(jié)來(lái)存儲(chǔ)這些基本數(shù)據(jù),我們把一個(gè)或連續(xù)的多個(gè)字節(jié)的存儲(chǔ)空間稱為一個(gè)存儲(chǔ)單元,每個(gè)存儲(chǔ)單元的地址用該存儲(chǔ)單元的第一個(gè)字節(jié)的地址來(lái)表示。例如,C語(yǔ)言中的short int、long int、char、double等基本數(shù)據(jù)類型在32位計(jì)算機(jī)系統(tǒng)中分別占用2、4、1、8個(gè)字節(jié),如果在內(nèi)存0x0F00地址處依次存儲(chǔ)short int、long int、char、double類型數(shù)據(jù)各一個(gè),那么這四個(gè)存儲(chǔ)單元的地址則分別為0x0F00、0x0F02、0x0F06、0x0F07,而下一個(gè)存儲(chǔ)單元的地址則為0x0F0F,如圖2所示。

      變量:是計(jì)算機(jī)存儲(chǔ)空間或存儲(chǔ)單元的具體化,通過(guò)一個(gè)易辨別的字符序列來(lái)標(biāo)識(shí)一個(gè)存儲(chǔ)空間或存儲(chǔ)單元,這樣能夠大大提高編程效率和代碼的可讀性。變量具有三個(gè)要素:1)名稱,2)類型,3)值,此外,變量還有一個(gè)隱含屬性,即地址。例如,圖1中的變量s、i三個(gè)變量,它們的要素及屬性如表1所示。

      指針:回頭再看Brian W.Kernighan的指針定義,指針本質(zhì)上也是一個(gè)變量,只不過(guò)它存儲(chǔ)的數(shù)據(jù)是一個(gè)表示地址的無(wú)符號(hào)整數(shù)。如圖1所示,變量pi、ps就是指針變量,我們把表1加上變量pi、ps后得到表2。

      三、指針定義及運(yùn)算

      在C語(yǔ)言中,表2中各變量的定義如下:

      char s = ‘a(chǎn), *ps; //定義并初始化char類型變量s,定義一個(gè)指向char類型變量的指針

      int i = 56, *pi; //定義并初始化int類型變量i,定義一個(gè)指向int類型變量的指針

      ps = &s; //將變量s的地址保存到ps變量中,則ps將指向s變量

      pi = &i; //將變量i的地址保存到pi變量中,則pi將指向i變量

      或者

      char s = ‘a(chǎn), *ps = &s ; //指針定義與賦值同時(shí)進(jìn)行

      int i = 56, *pi = &i;

      其中,*ps稱為指針,指針變量的定義格式為:

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

      在上述代碼中,通過(guò)ps = &s賦值后,*ps等價(jià)于s。結(jié)合圖1,對(duì)于0x05027存儲(chǔ)單元中的‘a(chǎn)有兩種訪問(wèn)方式:1)通過(guò)變量s來(lái)訪問(wèn)內(nèi)存地址0x05027的‘a(chǎn),這種訪問(wèn)方式稱為直接訪問(wèn)方式;2)指針變量ps中存放的是變量s的地址,通過(guò)*ps來(lái)訪問(wèn)0x05027的‘a(chǎn)需要兩個(gè)步驟,首先要從指針變量ps中讀取變量s的地址0x05027,再?gòu)牡刂?x05027中讀出‘a(chǎn),這種通過(guò)指針變量存取數(shù)據(jù)的訪問(wèn)方式稱為間接訪問(wèn)方式。

      跟指針密切相關(guān)的運(yùn)算符是*和&,它們均為一元運(yùn)算符,且互為逆運(yùn)算。

      &運(yùn)算符:取地址運(yùn)算符。放在普通變量的前面,作用是獲取對(duì)應(yīng)變量的存儲(chǔ)地址,例如變量i的值為56,而表達(dá)式&i的值則為0x05030,可使用以下語(yǔ)句進(jìn)行測(cè)試:

      inti = 56;

      printf ("%d, %p", i, &i);

      其運(yùn)行結(jié)果為:56, 0060FF34

      *運(yùn)算符:指針運(yùn)算符,又稱間接訪問(wèn)運(yùn)算符。放在指針變量的前面,作用是獲取指針變量中的地址所對(duì)應(yīng)的存儲(chǔ)單元中的數(shù)據(jù)??捎孟率龃a進(jìn)行驗(yàn)證。

      inti = 56, *pi; // 第1行

      pi = &i; // 第2行

      printf ("%d, %p, %p, %d", i, &i, pi, *pi); // 第3行

      運(yùn)行結(jié)果為: 56, 0060FF34, 0060FF34, 56

      其中,第1行的*表示定義指針變量,第3行中的*則表示指針運(yùn)算。

      四、指針的應(yīng)用

      學(xué)習(xí)指針的難點(diǎn)除了概念上的理解比較難以外,在應(yīng)用上有以下幾個(gè)比較難理解的地方。

      1.指針的初始化、釋放與NULL指針

      指針在使用中容易出問(wèn)題的主要環(huán)節(jié)就是指針的初始化和釋放后的處理。指針必須先申明,再賦值,然后才能使用,使用完后,需要用free()函數(shù)釋放所占用的存儲(chǔ)空間,最后還要對(duì)指針變量進(jìn)行置空,否則會(huì)出現(xiàn)意想不到的問(wèn)題。

      首先,在聲明指針變量后,如果不進(jìn)行初始化,那么該指針就是一個(gè)未初始化的指針,指針變量中的數(shù)據(jù)為內(nèi)存殘存數(shù)據(jù),如果不進(jìn)行初始化,就會(huì)指向一個(gè)未知的地方,得到的是一個(gè)無(wú)效數(shù)據(jù)。如下面的程序代碼。

      int *pt;

      printf ("%p, %p, %d\n", &pt, pt, *pt);

      運(yùn)行結(jié)果:0060FF30, 004013A0, -2082109099

      結(jié)果中第一個(gè)數(shù)字0060FF30表示的是指針變量pt本身的地址值;第二個(gè)數(shù)字004013A0是表示指針變量pt中的地址值,由于指針pt沒有初始化,所以指針pt變量中的地址值是原來(lái)內(nèi)存中的殘存數(shù)據(jù);第三個(gè)數(shù)字-2082109099則是殘存數(shù)據(jù)作為地址值所指內(nèi)存中的數(shù)據(jù),不是我們想要的數(shù)據(jù),屬于垃圾數(shù)據(jù)。

      其次,在指針使用完畢后,第一,要釋放指針?biāo)嫉膬?nèi)存空間,通過(guò)free()函數(shù)完成,第二,需要對(duì)不用的指針變量置空,即設(shè)置不再使用的指針變量的值為NULL,否則釋放空間后,指針中的地址值不會(huì)變,但是指針原來(lái)所指的存儲(chǔ)單元將成為未使用空間或分配給其他的變量使用。

      char *pta = (char *) malloc(30); //第1行

      strcpy(pta, "Hello C Language!"); //第2行

      printf ("%p \n", pta); //第3行

      free(pta); //第4行

      printf ("%p \n", pta); //第5行

      //if(pta != NULL); //第6行

      //strcpy(pta, "zfs"); //第7行

      pta = NULL; //第8行

      printf ("%p \n", pta); //第9行

      結(jié)果為:

      009C0DC0

      009C0DC0

      00000000

      第一個(gè)數(shù)字009C0DC0為malloc()函數(shù)申請(qǐng)30個(gè)字符空間的首個(gè)字節(jié)的地址,并將該地址值保存到了指針變量pta中;第二個(gè)數(shù)字009C0DC0是對(duì)指針變量pta進(jìn)行釋放處理后其中的值,可以看出,雖然釋放了pta所指向的存儲(chǔ)空間,但pta中的地址值仍然不變,pta所指向的存儲(chǔ)空間已經(jīng)回收或另作他用,pta指向了不可用內(nèi)存區(qū)域,成了野指針,而且不能使用(pta != NULL)進(jìn)行檢測(cè),所以第6、7行運(yùn)行會(huì)出錯(cuò);第三個(gè)數(shù)字00000000是將pta變量置空后pta中的值,即將NULL賦值給pta指針變量,pta即成為NULL指針(空指針),NULL的定義在C語(yǔ)言標(biāo)準(zhǔn)庫(kù)頭文件stddef.h中。宏定義如下:

      #undef NULL

      #if defined(__cplusplus)

      #define NULL 0

      #else

      #define NULL ((void *)0)

      #endif

      2.指針與數(shù)組

      C語(yǔ)言的數(shù)組表示的是一段連續(xù)的內(nèi)存空間,用來(lái)存儲(chǔ)多個(gè)指定類型的數(shù)據(jù),每個(gè)數(shù)組成員稱為一個(gè)數(shù)組元素,每個(gè)數(shù)組元素占用的字節(jié)數(shù)相等。數(shù)組和指針不是同一種結(jié)構(gòu),不可以互相轉(zhuǎn)換,但是數(shù)組變量則是指向了數(shù)組的第一個(gè)元素的內(nèi)存地址,如圖3所示。

      short int ai[5]= {27, 36, 51, 110, 97}; //第1行

      short int *ptai; //第2行

      ptai = ai; //第3行

      在C語(yǔ)言中可以把數(shù)組變量直接賦值給指針,但不能把指針變量賦值給數(shù)組。如果把一個(gè)數(shù)組變量值賦給指針,實(shí)際上是把指向數(shù)組第一個(gè)元素的地址賦給指針。第2、3行可以理解為:

      short int *ptai = &ai[0];

      或者

      short int *ptai;

      ptai = &ai[0];

      所以ai[0]與*ptai是等價(jià),由于數(shù)組中的元素是等長(zhǎng)的,因此,ai[1]與*(ptai + 1)、ai[2]與*(ptai + 2)也是等價(jià)的,以此類推。但是,要注意的是ptai + 1、ptai + 2中的1、2并不是按字節(jié)計(jì)算的偏移量,而是按short int類型計(jì)算的偏移量。

      五、總結(jié)

      指針雖然比較難以理解和掌握,需要許多計(jì)算機(jī)底層的知識(shí)作支撐,但它卻是C語(yǔ)言的精髓所在,是C語(yǔ)言的重要特性,能夠充分展現(xiàn)C語(yǔ)言的強(qiáng)大魅力。實(shí)際上,我們只要從變量的本質(zhì)、內(nèi)存地址、計(jì)算機(jī)尋址原理等多方面進(jìn)行了解和貫通,指針概念以及指針的相關(guān)應(yīng)用也就不難理解了。而且,通過(guò)對(duì)指針的深入了解和學(xué)習(xí),能夠更加高效和靈活地使用數(shù)組、字符串、結(jié)構(gòu)體、各種線性非線性數(shù)據(jù)結(jié)構(gòu)、內(nèi)存的動(dòng)態(tài)分配以及文件的存取等。所以說(shuō),學(xué)好了指針,才能夠?qū)W好C語(yǔ)言。

      責(zé)任編輯朱守鋰

      猜你喜歡
      運(yùn)算符存儲(chǔ)單元數(shù)組
      一種28 nm工藝下抗單粒子翻轉(zhuǎn)SRAM的12T存儲(chǔ)單元設(shè)計(jì)
      JAVA稀疏矩陣算法
      老祖?zhèn)魇诨具\(yùn)算符
      JAVA玩轉(zhuǎn)數(shù)學(xué)之二維數(shù)組排序
      浮點(diǎn)類型有效位數(shù)計(jì)算與應(yīng)用分析
      一種成本更低的全新靜態(tài)DRAM存儲(chǔ)單元
      MiR-125a-5p is Upregulated in Plasma of Residents from An Electronic Waste Recycling Site
      尋找勾股數(shù)組的歷程
      C++運(yùn)算符重載剖析
      表達(dá)式求值及符號(hào)推導(dǎo)
      外汇| 开平市| 武安市| 赫章县| 荣昌县| 潼关县| 涞源县| 宣威市| 漳平市| 邵东县| 庆元县| 云林县| 绵阳市| 济阳县| 浮梁县| 射阳县| 闻喜县| 三穗县| 信丰县| 濉溪县| 海晏县| 邛崃市| 聂拉木县| 玉环县| 汝阳县| 林口县| 道孚县| 酉阳| 乌兰察布市| 河源市| 梁山县| 潢川县| 阿荣旗| 贡嘎县| 菏泽市| 北辰区| 海口市| 扶风县| 龙胜| 大化| 罗源县|