• 
    

    
    

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

      ?

      淺析C程序設(shè)計(jì)中指針的奧秘

      2010-09-12 05:16:46
      長治學(xué)院學(xué)報(bào) 2010年2期
      關(guān)鍵詞:數(shù)組指針C語言

      李 瑛

      (太原師范學(xué)院 計(jì)算機(jī)系,山西 太原 030001)

      淺析C程序設(shè)計(jì)中指針的奧秘

      李 瑛

      (太原師范學(xué)院 計(jì)算機(jī)系,山西 太原 030001)

      在C語言中,指針是廣泛使用的一種數(shù)據(jù)類型,起著不可低估的作用,同時它也是C語言的一個精華,極大地豐富了C語言的功能。文章結(jié)合作者的教學(xué)實(shí)踐經(jīng)驗(yàn),針對學(xué)生在學(xué)習(xí)C語言指針時遇到的問題進(jìn)行總結(jié)和歸納。便于為以后的教學(xué)提供參考。

      指針;變量;地址;C語言

      在C語言中,指針是廣泛使用的一種數(shù)據(jù)類型,起著不可低估的作用,同時它也是C語言的一個精華。有人說,沒有學(xué)過指針就沒有學(xué)過C語言,可見,指針在C語言中作用是不可替代的。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu);能方便地使用數(shù)組和字符串;并能象匯編語言一樣處理內(nèi)存地址,從而編出精練而高效的程序。在C語言程序設(shè)計(jì)中,指針極大地豐富了C語言的功能。能否正確理解和使用指針是我們是否掌握C語言的一個標(biāo)志。但是由于指針太過靈活,一旦使用不當(dāng),不僅錯誤難查,而且會出現(xiàn)意想不到的錯誤。因此,要編出正確而高效的程序必須正確地理解和使用指針。針對初學(xué)者對C語言指針的理解不夠透徹,作者根據(jù)在C語言教學(xué)和使用方面的經(jīng)驗(yàn),對指針做了詳細(xì)的闡述。

      1 指針的含義

      指針是一種特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的一個地址。對指針的理解需要搞清四方面的內(nèi)容:指針的類型;指針?biāo)赶虻念愋停恢羔樀闹祷蛘呓兄羔標(biāo)赶虻膬?nèi)存區(qū);指針本身所占據(jù)的內(nèi)存區(qū)。

      1.1 指針的類型

      從語法的角度看,只要把指針聲明語句里的指針名字去掉,剩下的部分就是這個指針的類型。這是指針本身所具有的類型。讓我們看看例中指針的類型:

      (1)int*pointer; //指針的類型是 int*

      (2)int(*pointer)[3];//指針的類型是int(*)[3]

      1.2 指針?biāo)赶虻念愋?/h3>

      當(dāng)通過指針來訪問指針?biāo)赶虻膬?nèi)存區(qū)時,指針?biāo)赶虻念愋蜎Q定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當(dāng)做什么來看待。從語法上看,只須把指針聲明語句中的指針名字和名字左邊的指針聲明符*去掉,剩下的就是指針?biāo)赶虻念愋?。例如?/p>

      (1)int*pointer; //指針?biāo)赶虻念愋褪莍nt

      (2)int(*pointer)[3];//指針?biāo)赶虻牡念愋褪莍nt()[3]

      指針的類型(即指針本身的類型)和指針?biāo)赶虻念愋褪莾蓚€概念。對C越來越熟悉時就會發(fā)現(xiàn),把與指針攪和在一起的“類型”這個概念分成“指針的類型”和“指針?biāo)赶虻念愋汀眱蓚€概念,是精通指針的關(guān)鍵點(diǎn)之一。

      1.3 指針的值

      指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當(dāng)作一個地址,而不是一個一般的數(shù)值。指針?biāo)赶虻膬?nèi)存區(qū)就是從指針的值所代表的那個內(nèi)存地址開始,長度為sizeof(指針?biāo)赶虻念愋停┑囊黄瑑?nèi)存區(qū)。以后,如果說一個指針的值是XX,就相當(dāng)于說該指針指向了以XX為首地址的一片內(nèi)存區(qū)域;一個指針指向了某塊內(nèi)存區(qū)域,就相當(dāng)于說該指針的值是這塊內(nèi)存區(qū)域的首地址。

      指針?biāo)赶虻膬?nèi)存區(qū)和指針?biāo)赶虻念愋褪莾蓚€完全不同的概念。在上面的例子中,指針?biāo)赶虻念愋鸵呀?jīng)有了,但由于指針還未初始化,因此它所指向的內(nèi)存區(qū)是不存在的,或者說是無意義的。所以,每遇到一個指針,都應(yīng)該問問:這個指針的類型是什么?指針指的類型是什么?該指針指向了哪里?

      1.4 指針本身所占的內(nèi)存區(qū)

      利用sizeof(指針的類型)函數(shù),可以測試指針本身所占內(nèi)存的大小,在16位平臺里,指針本身占據(jù)了2個字節(jié)的長度。

      2 指針運(yùn)算

      指針是可以進(jìn)行的算術(shù)運(yùn)算的。指針可以加上或減去一個整數(shù)。指針的這種運(yùn)算的意義和通常的數(shù)值的加減運(yùn)算的意義是不一樣的。例如:

      int a;int*pointer=a;pointer++;

      在上例中,指針pointer的類型是int*,它指向的類型是int,它被初始化為指向整形變量a。接下來的語句中,指針pointer被加了1,編譯器是這樣處理的:它把指針pointer的值加上了sizeof(int)(在16位程序中,是被加上了2),由于地址是用字節(jié)做單位的,故pointer所指向的地址由原來的變量a的地址向高地址方向增加了2個字節(jié)。

      用一個指針和一個循環(huán)來遍歷一個數(shù)組,例:int array[20];

      這個例子將整型數(shù)組中各個元素的值加1。由于每次循環(huán)都將指針pointer加1所以每次循環(huán)都能訪問數(shù)組的下一個元素。

      所以,一個指針pointerold加上一個整數(shù)n后,結(jié)果是一個新的指針pointernew,pointernew的類型和pointerold的類型相同,pointernew所指向的類型和pointerold所指向的類型也相同。pointernew的值將比pointerold的值增加了n乘sizeof(pointerold所指向的類型)個字節(jié)。就是說,pointernew所指向的內(nèi)存區(qū)將比pointerold所指向的內(nèi)存區(qū)向高地址方向移動了n乘sizeof(pointerold所指向的類型)個字節(jié)。一個指針pointerold減去一個整數(shù)n后,結(jié)果是一個新的指針pointernew,pointernew的類型和pointerold的類型相同,pointernew所指向的類型和pointerold所指向的類型也相同。pointernew的值將比pointerold的值減少了n乘sizeof(pointerold所指向的類型)個字節(jié),就是說,pointernew所指向的內(nèi)存區(qū)將比pointerold所指向的內(nèi)存區(qū)向低地址方向移動了n乘sizeof(pointerold所指向的類型)個字節(jié)。

      3 運(yùn)算符&和*

      &是取地址運(yùn)算符。若a是一個變量,&a的運(yùn)算結(jié)果是一個指針,指針的類型是a的類型加個*,指針?biāo)赶虻念愋褪莂的類型,指針?biāo)赶虻牡刂?,那就是a的地址。

      *p的結(jié)果是p所指向的內(nèi)容,并且具有如下特點(diǎn):它的類型是p指向的類型,它所占用的地址是p所指向的地址。例:

      int a=12;int b;int*p;int**pointer;

      p=&a;//&a的結(jié)果是一個指針,類型是int*,指向的類型是int,指向的地址是a的地址。

      *p=24;//*p的結(jié)果,在這里它的類型是int,它所占用的地址是p所指向的地址,顯然,*p就是變量a。

      *pointer=&b;//*pointer是個指針,&b 的結(jié)果也是個指針,且這兩個指針的類型和所指向的類型是一樣的,所以用&b來給*pointer賦值就是毫無問題的了。

      **pointer=34; //*pointer的結(jié)果是 pointer所指向的東西,在這里是一個指針,對這個指針再做一次*運(yùn)算,結(jié)果就是一個int類型的變量。

      4 數(shù)組和指針的關(guān)系

      數(shù)組的數(shù)組名其實(shí)可以看作一個指針。如下例:

      int array[10]={0,1,2,3,4,5,6,7,8,9},value;

      value=array[0];//也可寫成:value=*array;

      value=array[3];//也可寫成:value=*(array+3);

      2.2 堅(jiān)持以人為本的原則,分層對待員工的各自情況。國有企業(yè)職工出身結(jié)構(gòu)的多樣性,往往體現(xiàn)在職工的年齡、學(xué)歷、經(jīng)歷、性別,家庭都是造成不同的思想狀態(tài)的因素,對職工進(jìn)行同類分類,單獨(dú)為同類職工制定相關(guān)的教育輔導(dǎo)方式,能夠解除職工的一些顧慮,真實(shí)準(zhǔn)確、及時地了解員工的思想動態(tài),化解企業(yè)內(nèi)部的矛盾,營造和諧融洽的企業(yè)工作環(huán)境,提高企業(yè)的生產(chǎn)經(jīng)營效率。

      上例中,一般而言數(shù)組名array代表數(shù)組本身,類型是int[10],但如果把a(bǔ)rray看做指針的話,它指向數(shù)組的第0個單元,類型是int*,所指向的類型是數(shù)組單元的類型,即int。因此*array等于0就一點(diǎn)也不奇怪了。同理,array+3是一個指向數(shù)組第3,所以*(array+3)等于3。其它依此類推。

      聲明了一個數(shù)組TYPE array[n],則數(shù)組名稱array就有了兩重含義:第一,它代表整個數(shù)組,它的類型是TYPE[n];第二,它是一個指針,該指針的類型是TYPE*,該指針指向的類型是TYPE,也就是數(shù)組單元的類型,該指針指向的內(nèi)存區(qū)就是數(shù)組第0號單元,該指針自己占有單獨(dú)的內(nèi)存區(qū)。注意它和數(shù)組第0號單元占據(jù)的內(nèi)存區(qū)是不同的。該指針的值是不能修改的,即類似array++的表達(dá)式是錯誤的。在不同的表達(dá)式中數(shù)組名array可以扮演不同的角色。在表達(dá)式sizeof(array)中,數(shù)組名array代表數(shù)組本身,故這時sizeof函數(shù)測出的是整個數(shù)組的大小。在表達(dá)式*array中,array扮演的是指針,因此這個表達(dá)式的結(jié)果就是數(shù)組第0號單元的值。sizeof(*array)測出的是數(shù)組單元的大小。表達(dá)式array+n(其中 n=0,1,2,....。)中,array扮演的是指針,故array+n的結(jié)果是一個指針,它的類型是TYPE*,它指向的類型是TYPE,它指向數(shù)組第n號單元。故sizeof(array+n)測出的是指針類型的大小。

      5 指針類型轉(zhuǎn)換

      當(dāng)我們初始化一個指針或給一個指針賦值時,賦值號的左邊是一個指針,賦值號的右邊是一個指針表達(dá)式。在前面所舉的例子中,絕大多數(shù)情況下,指針的類型和指針表達(dá)式的類型是一樣的,指針?biāo)赶虻念愋秃椭羔槺磉_(dá)式所指向的類型是一樣的。例:

      float f=12.3;float*fpointer=&f;int*p;

      在上面的例子中,假如想讓指針p指向?qū)崝?shù)f,那么p=&f是錯誤的。因?yàn)橹羔榩的類型是int*,它指向的類型是int。表達(dá)式&f的結(jié)果是一個指針,指針的類型是float*,它指向的類型是float。兩者不一致,直接賦值的方法是不行的。為了達(dá)到目的,需要進(jìn)行“強(qiáng)制類型轉(zhuǎn)換”:p=(int*)&f;如果有一個指針p,需要把它的類型和所指向的類型改為TYEP*TYPE,那么語法格式是:(TYPE*)p;

      這樣強(qiáng)制類型轉(zhuǎn)換的結(jié)果是一個新指針,該新指針的類型是TYPE*,它指向的類型是TYPE,它指向的地址就是原指針指向的地址。而原來的指針p的一切屬性都沒有被修改。

      6 指針的安全問題

      看下面的例子:

      char s='a'; int*pointer; pointer=(int*)&s;*pointer=1298;

      指針pointer是一個int*類型的指針,它指向的類型是int。它指向的地址就是s的首地址。在32位程序中,s占一個字節(jié),int類型占四個字節(jié)。最后一條語句不但改變了s所占的一個字節(jié),還把和s相臨的高地址方向的三個字節(jié)也改變了。這三個字節(jié)是干什么的?只有編譯程序知道,而寫程序的人是不太可能知道的。也許這三個字節(jié)里存儲了非常重要的數(shù)據(jù),也許這三個字節(jié)里正好是程序的一條代碼,而由于對指針的馬虎應(yīng)用,這三個字節(jié)的值被改變了!這會造成崩潰性的錯誤。

      如下例:

      1、char a;

      2、int*pointer=&a;

      3、pointer++;

      4、*pointer=115;

      該例子完全可以通過編譯,并能執(zhí)行。但是第3句對指針pointer進(jìn)行自加1運(yùn)算后,pointer指向了和整形變量a相鄰的高地址方向的一塊存儲區(qū)。這塊存儲區(qū)里的具體內(nèi)容并不明確,有可能它是一個非常重要的數(shù)據(jù),甚至可能是一條代碼。而第4句竟然往這片存儲區(qū)里寫入一個數(shù)據(jù)!這是嚴(yán)重的錯誤。所以在使用指針時,程序員心里必須非常清楚指針的指向。在用指針訪問數(shù)組的時候,也要注意不要超出數(shù)組的低端和高端界限,否則也會造成類似的錯誤。

      [1]王敬華,等.C 語言程序設(shè)計(jì)教程[M].北京:清華大學(xué)出版社.2006.264-380.

      [2]譚浩強(qiáng).C語言程序設(shè)計(jì)[M].北京:清華大學(xué)出版社,1995,157-212.

      [3]吳斌.C語言指針的教學(xué)[J].安徽職業(yè)技術(shù)學(xué)院學(xué)報(bào).2004,(9):67-69.

      (責(zé)任編輯 李學(xué)斌)

      TP312

      A

      1673-2014(2010)02-0026-03

      2010—04—02

      李 瑛(1973— ),女,河北保定人,碩士,講師,主要從事計(jì)算機(jī)人工智能研究。

      猜你喜歡
      數(shù)組指針C語言
      JAVA稀疏矩陣算法
      基于Visual Studio Code的C語言程序設(shè)計(jì)實(shí)踐教學(xué)探索
      JAVA玩轉(zhuǎn)數(shù)學(xué)之二維數(shù)組排序
      偷指針的人
      基于C語言的計(jì)算機(jī)軟件編程
      電子制作(2018年16期)2018-09-26 03:27:08
      為什么表的指針都按照順時針方向轉(zhuǎn)動
      高職高專院校C語言程序設(shè)計(jì)教學(xué)改革探索
      尋找勾股數(shù)組的歷程
      基于改進(jìn)Hough變換和BP網(wǎng)絡(luò)的指針儀表識別
      電測與儀表(2015年5期)2015-04-09 11:30:42
      論子函數(shù)在C語言數(shù)據(jù)格式輸出中的應(yīng)用
      郴州市| 牡丹江市| 金门县| 瑞昌市| 永定县| 当阳市| 江永县| 黄平县| 襄垣县| 安宁市| 罗甸县| 麻城市| 余姚市| 彭州市| 资兴市| 阜阳市| 靖远县| 泌阳县| 定日县| 南宁市| 横峰县| 建始县| 泊头市| 绵阳市| 宣威市| 宜宾市| 鹿泉市| 西安市| 宁阳县| 肇庆市| 凯里市| 绵竹市| 观塘区| 泰安市| 屏东市| 滁州市| 从化市| 昌图县| 梁平县| 钦州市| 金门县|