亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        指針教學內(nèi)容改革之一

        2009-03-17 09:14:32王恒濱
        計算機教育 2009年3期
        關鍵詞:指針教學內(nèi)容

        文章編號:1672-5913(2009)02-0077-05

        摘 要:C語言指針教學內(nèi)容組織近乎千篇一律,除相關概念至今未見在教材中求精外,理論基礎的介紹既不精準又不一致更不直觀,大體停留在羅列各種使用情形上。本文選取了已投入教學實踐并取得良好效果的自編講義中的一段,以展示教改成果。其中的字面指針能使介紹直觀化。

        關鍵詞:教學內(nèi)容;C語言;指針

        中圖分類號:G642

        文獻標識碼:B

        1 基本指針類型

        C語言中,指針是一種特殊類型的整型值,所以也說成是指針值。指針與地址不同,地址是反映計算機存儲介質(zhì)邏輯構造的物理概念。存儲介質(zhì)由字節(jié)組成,每個字節(jié)都有一定的序號(如0,1,2,3,…,100,101,…,1000,1001,……),這些連續(xù)的序號就是它們的物理地址。地址作為字節(jié)的序號,用整數(shù)就能表示。

        然而僅僅地址并不能反映該地址處的若干字節(jié)是由什么類型的變量或數(shù)組所用,正像僅憑“長安大街100號”并不能指明該處是大商場還是小店鋪,乃至是圍有幾棟樓的居民小區(qū)。為了描述“是由什么所用”這層含義,引入了指針概念,并給出了指針類型及其表達方法。

        有了指針類型,指針就能由整型值地址轉化而成,在程序需要指針時有計可施。

        指針類型并不像結構體類型,需要專門做出類型聲明,而只需在已有的類型名上添加運算符就能表達,甚至像數(shù)組類型之類,只需添加運算符[]和其中的整型常量值。

        盡管有些指針類型的表達可能非常復雜,但這里僅討論表達簡潔的基本指針類型,即在已有的非數(shù)組類型后跟隨星號。例如:

        short * char * struct tag *

        (假設struct tag是已聲明的結構體類型,且全文有效)。

        如果想把程序中出現(xiàn)的整數(shù)2000看成是存儲介質(zhì)序號2000字節(jié)的地址,就必須配合使用指針類型。例如:

        ① (short *)2000

        ② (char *)2000

        ③ (struct tag *)2000

        都是合理的,參照-2000是字面負整數(shù)的說法,它們都可以認為是字面指針。此時,其中的2000代表地址,不過它們還有另一層含義,那就是地址2000處的若干字節(jié),在①看來是用兩個字節(jié)為short型變量所用;在②看來是用一個字節(jié)為char型變量所用,等。

        1.1 指針

        指針是整型值配上指針類型,此時的整型值代表地址。例如,假設k是整型變量,則

        (short *)k (long *)(2*k+1)

        (char *)2000 (struct tag *)3000

        的結果都是指針。若k的值為1000,那么(short *)k與(long *)(2*k+1)分別等于

        (short *)1000 與 (long *)2001

        為了敘述方便,可以稱:(1)指針類型星號前的類型為基類型,(2)類型后的整型值為指針地址,如下表:

        1.2 指針變量

        這種類型的變量可以用來存儲指針,定義指針變量要用指針類型來完成。以下寫出的都是指針變量的定義。

        short * p1; char * p2;

        struct tag * p3;

        之后,p1、p2、p3便都是指針變量名。

        使用賦值運算可以讓指針變量存儲指針,但類型應當一致。例如

        p1 = (short *)k; p2 = (char *)2000;

        p3 = (struct tag *)2000;

        都是正確的(k的意義同上文)。

        用指針變量來存儲指針,不過是存儲了指針地址,指針類型的信息全憑這個指針變量的類型體現(xiàn)。例如,p2存儲的是2000,由于它是char * 型的指針變量,所以它的值為:

        (char *)2000

        指針變量對應內(nèi)存的字節(jié)數(shù),由編程環(huán)境中設置的模式?jīng)Q定,small模式等為2字節(jié),large模式等為4字節(jié)。

        定義指針變量的方法,可以動態(tài)地描述成:在已有變量定義的基礎上,在變量名前加星號。例如

        int p1, v, p2; => int *p1, v, *p2;

        那么,p1,p2變成為指針變量。

        注意,在星號的前后增減空格不會影響語義。

        1.3 輸出指針

        凡是能夠輸出整型值的格式輸出,都可以輸出指針的指針地址。但不能忘記指針是在2字節(jié)的small模式下還是在4字節(jié)的large模式下。

        %p格式的printf()專門用來輸出指針的指針地址。不同的是,它能自動察覺程序完成時的編程環(huán)境是什么模式,以便相應地采取類似%x格式或%lx格式的輸出,但相比之下輸出形式略有差異:

        ●small模式時,輸出地址的4位十六進制數(shù)字。

        ●large模式時,輸出地址的8位十六進制數(shù)字,且兩個4位之間用冒號隔開。

        例如,

        printf("%p", (int *)30);

        在small模式下,將輸出001e;在large模式下,將輸出0000:001e

        1.4 直接代表指針

        1.4.1一維數(shù)組名代表指針

        C語言的一維數(shù)組名和變量名,在語義上存在著本質(zhì)區(qū)別。盡管它們都唯一地對應一塊內(nèi)存,并且內(nèi)存塊的首字節(jié)地址正是這種對應的確切反映。然而,在程序中簡單地使用變量名意味著要向那塊內(nèi)存儲存數(shù)據(jù)或要從中取得數(shù)據(jù);簡單地使用一維數(shù)組名卻意味著僅僅要利用那塊內(nèi)存的首字節(jié)地址形成的有相同基類型的指針。亦即,指針的基類型就是數(shù)組的基類型。由于內(nèi)存塊的位置是確定的,所以經(jīng)??吹降恼f法類似于:數(shù)組名是指針常量。

        可以用printf("%p", 數(shù)組名);來輸出數(shù)組對應內(nèi)存塊的首字節(jié)地址。這從一個側面表明,盡管數(shù)組的內(nèi)存是系統(tǒng)分配的,但我們還是可以知道它在什么地方。

        1.4.2 字符串常量代表指針

        在程序中,經(jīng)??梢钥吹竭@樣的寫法:

        p = "e:\turboc2\student.dat";

        其中,p是char* 型的指針變量。實際上,系統(tǒng)要為這樣的字符串常量專門開辟一塊內(nèi)存來存儲它包含的字符??墒?,它在程序中留下的可供直接使用的只有char* 型的指針,指針地址就是那塊內(nèi)存的首字節(jié)地址,所以才要用一個指針變量來保存,以便之后隨時可用。

        在此額外提一句,整型常量的存儲位置很隱蔽,但幸好沒必要知道。表達式計算的中間結果存儲在什么地方也是隱蔽的。

        有了以上兩點認識,就可以這樣說,%s格式的輸出部分可以是指針值,只要指針地址處的若干字節(jié)存儲了恰當?shù)淖址?。至于在輸出部分處寫的是字符串常量還是數(shù)組名,都無關緊要。

        2 基本指針的運算

        指針能參與的運算很有限。除賦值運算以外,還有其他七個種類。前四個種類分別是“*”、“[ ]”、“&”和強制指針類型轉換運算。

        2.1 指針的指針運算

        * —— 除了用來構成指針類型之外,還可以出現(xiàn)在指針前,與指針一起構成一個基類型的變量?!?指針”變量的內(nèi)存就是指針地址處的若干字節(jié)。它是單目運算符。

        例如,*(int *)2000是一個int型的變量,這個表達式的值是這個變量的值,而不是2000。

        再如,若an是int[100]型數(shù)組名,*an就為int型的變量,也就是an的第0號元素an[0]。

        再如,*"Hello"是一個char型的變量,其中存儲的是字符'H'。

        2.2 指針的下標運算

        [ ] —— 除用來構成數(shù)組類型之外,當其間包含有整型值并出現(xiàn)在指針后,將與指針結合成一個基類型的變量?!爸羔榌整型值]”變量就是“*(指針+整型值)”變量。它是雙目運算,需要一個指針和一個整型值。例如:

        ((int*)2000)[4] <=> *((int*)2000 + 4)

        是一個int型的變量。

        再如,若a是int[100]型數(shù)組名,那么

        a[4] <=> *(a + 4)

        是一個int型的變量,也就是a的第4號元素。請不必為先有雞——指針a與4做[ ]運算為a[4],還是先有蛋——數(shù)組a的第4號元素為a[4]所困,只需記?。合聵俗兞烤褪亲隽讼聵诉\算所得的變量。再如

        "Hello"[4] <=> *("Hello"+4)

        是一個char型的變量,存儲的是字符'o'。

        2.3 指針的求取運算

        & —— 是取指針運算符。把它置于變量前,算出的是該變量的指針,這個指針以變量的類型為基類型,以變量內(nèi)存的首字節(jié)地址為其指針地址。

        例如,有如下變量定義,并假設它們的內(nèi)存首字節(jié)地址分別為:1000,1002,1003

        short v1; char v2; struct tag v3;

        那么,&v1、&v2、&v3的值分別為:

        (short *)1000 (char *)1002

        (struct tag *)1003

        2.4 強制指針類型轉換運算

        (指針類型)——跟其他強制類型轉換運算符的構成一樣,比如(short *)、(char *)……都是這樣的運算符。把它們置于z指針或整型值之前,結果就是所要類型的指針。例如

        (int *)"Hello"

        就能從char*型的指針轉換成int*型的指針,指針地址不變。再如,曾經(jīng)寫出的指針

        (short *)k (long *)(2*k+1)

        (char *)2000 (struct tag *)3000

        其實分別為:

        對k的值做了(short *)運算

        對2*k+1的值做了(long *)運算

        對2000做了(char *)運算

        對3000做了(struct tag *)運算

        作為類比

        -k,-(2*k+1),-2000

        分別為:對k、2*k+1和字面整數(shù)2000的值做了求負運算,等。

        后三個種類分別是加減運算、關系運算和邏輯運算

        2.5 指針的加減運算

        i) 指針增減值:指針作為第一運算對象和整型值相加減。結果仍為同類型的指針,但指針地址加減了整型值的倍數(shù),具體幾倍要看基類型對應幾個字節(jié)。例如

        (short *)2000+10等于(short *)(2000+10*2) 即(short *)2020

        ii) 兩指針相減:類型相同的指針可以相減。結果的類型,若small模式為short,若large模式為long,得到的整型值等于指針地址之差除以基類型的字節(jié)數(shù)。例如

        (long *)2000 – (long *)1800

        => (2000 – 1800) / 4 => 50

        所以計算結果,或是50或是50L。

        數(shù)組的兩個元素的指針與它倆的下標之間的關系,用這類運算確定極為方便。

        比如a是任意數(shù)組,i和j是兩個下標,那么

        &a[i] + j - i = &a[j]

        &a[j] - &a[i] = j - i

        特別地

        a + i = &a[i] &a[i] - a = i

        2.6 指針的比較運算

        相同類型的指針可做比較運算。計算結果不是0就是1。比較僅僅使用指針地址。例如,

        (int *)3 > (int *)2

        的結果為1。

        如果使用減法,把(int *)3 – (int *)2的結果為0作為(int*)3等于(int*)2的依據(jù),就犯錯誤了!特別地,整數(shù)0可以跟任何類型的指針做比較。

        2.7 指針的邏輯運算

        不同類型的指針以及整型值之間,可以做邏輯運算,計算結果非0即1。指針的邏輯“真”、“假”僅以指針地址是否為0作為依據(jù)。

        例如,假設有int* pi, v; char* pc;并且都存儲了適當?shù)闹?。那?/p>

        pi && v || pc

        是正確的表達式。若它們存儲的分別為(int*)0、10、(char*)20,則上式的計算過程為:

        ((int*)0 && 10) || pc => 0 || (char*)20 => 1

        即結果為“真”。

        指針運算和下標運算表明,C語言中存在著純屬表達式形式的變量。使用上,這種表達式的整體相當于變量名。

        正是基于指針能夠通過運算得到變量這一事實,便有了較直觀的說法:指針指向變量。甚至用箭頭來圖示“指向”,方法如下圖所示。其中假設a是一維數(shù)組、v是變量,p和q是指針變量,分別存儲了指針&v和a(言下之意,p、q有適合的指針類型)。

        注:箭頭起始方框內(nèi)是存儲的指針,方框外給出的是變量名或相當于變量名的表達式。

        必須心中有數(shù),盡管指針值是多少并不會妨礙用指針運算或下標運算得到變量,然而這樣得到的變量,其內(nèi)存是否靠得住并沒有論及。這和《建筑施工手冊》僅介紹了房屋建造的方法,至于私搭亂建將產(chǎn)生什么后果并未涉及一樣。都需另立專題說明。

        2.8 指針類型的自動轉換

        1) 值,任何類型的指針值,甚至整型值,都可以作為賦值表達式的右端,最后將自動轉化為賦值運算符左端指針變量的類型。

        2) 減,硬讓不同類型的指針做減法時,減號右邊的指針將自動轉化為左邊的指針類型。

        3) 較,指針也可以硬性地和任何其他類型的指針,甚至整型值做比較,而利用的僅僅是指針地址或整型值。

        盡管以上三條行得通,但編譯系統(tǒng)還是有可能給出警告信息,以表明那么做是不希望的。作為例子,特給出以下3個式子的計算。

        (short*)50 – 10

        => (short*)(50 – 10*2)

        => (short*)30

        (short*)50 – (char*)10

        => (short*)50 – (short*)10

        => (50 – 10)/2 => 20

        (char*)50 – (short*)10

        => (char*)50 – (char*)10

        => (50 – 10)/1 => 40

        3 相關運算的優(yōu)先級與結合性

        這里僅討論前四個種類的運算符:*、[ ]、&和強制指針類型轉換運算符。

        其中,“[]”的優(yōu)先級最高,且結合性從左到右;“*”、“&”以及“(指針類型)”運算符的優(yōu)先級次之,等同于其他單目運算符,且它們的結合性也相同,都是從右到左。順便提一下,具備這種結合性的雙目運算符只有賦值運算符“=”。

        C語言對表達式的計算求解依賴于運算符的優(yōu)先級和結合性。作為練習,在此給出7例,并做了適度推導。

        1) (long*)(short *)2000 = (long *)2000

        因 (short *)2000 的指針地址為2000,配上最后運算生效的強制類型轉化運算符 (long*),必然等于右側。

        2) (short *)2000 + 10

        ≠ (short *)(2000 + 10)

        因 (short *)2000 + 10 = (short *)2020 而 (short *) (2000 +10) = (short *)2010

        3) *((short *)2000 + 5)

        <≠> *(short *)2000 + 5

        因 *( (short *)2000 + 5 ) <=>

        *( (short *)2010 )

        再由于“(short *)”與指針運算符“*”的優(yōu)先級相同,結合性“從右到左”,所以括號可以去掉,即為:

        * (short *)2010

        此乃變量,可以給它存儲值或從中得到值。而

        *(short *)2000+5

        => (*(short *)2000) + 5 => 變量 + 5

        只能算得一個值

        【引申】如果把指針 (short *)2000用指針變量p替換,相當于

        *(p + 5) <≠> *p + 5

        4) (long *)(2*k+1) ≠> (long *)2*k+1

        因“(long *)”的優(yōu)先級高于乘法運算符“*”,故

        (long *)2*k+1 => ((long *)2)*k+1

        => 指針* k + 1,

        可是指針不能做乘法運算。

        5) ((short *)2000)[5]

        ≠> (short *)2000[5]

        因“[ ]”的優(yōu)先級高于“(int *)”,故

        (int *)2000[5] => (int *)( 2000[5] )

        可是整型值與整型值之間不能做下標運算。

        6) &*(int *)2000 = (int *)2000

        因 &*(int *)2000 => & (* (int *)2000)

        而變量 * (int *)2000 的首地址為2000,基類型為int,取指針的結果必然為:(int *)2000

        【引申】如果把指針 (int *)2000用指針變量p替換,相當于

        &*p = p

        7) *&*(int *)2000 <=> *(int *)2000

        因 *&*(int *)2000 <=>

        *(&* (int *)2000) <=> *( (int *)2000)

        <=> * (int *)2000

        【引申】如果把變量 *(int *)2000用變量v替換,相當于

        *&v <=> v

        從后兩例可見,“&”與“*”是一對互逆運算符。

        補充說明:1)嚴格地說,C語言沒有字面負整數(shù);2)本文僅就Turbo C 2.0開發(fā)環(huán)境而言。

        參考文獻:

        [1] 王恒濱,閆東升. 關于C語言指針定義的討論[J]. 遼寧財專學報,2004.

        [2] 傅育熙等譯. 程序設計語言:設計與實現(xiàn)(第四版)[M]. 北京:電子工業(yè)出版社,2001.

        [3] 金戈,湯凌等譯. 代碼大全(第二版)[M]. 北京:電子工業(yè)出版社,2006.

        猜你喜歡
        指針教學內(nèi)容
        垂懸指針檢測與防御方法*
        軟件學報(2020年6期)2020-09-23 07:31:52
        偷指針的人
        娃娃畫報(2019年5期)2019-06-17 16:58:10
        挖掘數(shù)學教學內(nèi)容所固有的美
        為什么表的指針都按照順時針方向轉動
        “啟蒙運動”一課教學內(nèi)容分析
        “清末新政”也可作為重要的教學內(nèi)容
        基于改進Hough變換和BP網(wǎng)絡的指針儀表識別
        電測與儀表(2015年5期)2015-04-09 11:30:42
        線性代數(shù)課程學—研—用教學內(nèi)容及模式探索
        精心設計教案 重構教學內(nèi)容
        中學語文(2015年18期)2015-03-01 03:50:47
        ARM Cortex—MO/MO+單片機的指針變量替換方法
        亚洲人精品亚洲人成在线| 亚洲性感毛片在线视频| 黄片视频免费观看蜜桃| 日本高清视频xxxxx| 国内精品久久久久久久久久影院 | 青娱乐极品视觉盛宴国产视频| 236宅宅理论片免费| 国产一线视频在线观看高清| 男女啪啪动态视频在线观看| 暖暖 免费 高清 日本 在线| 欧美日韩精品一区二区在线观看| 欧美精品日韩一区二区三区| 精品高清一区二区三区人妖| 私人vps一夜爽毛片免费| 永久免费无码av在线网站| 色偷偷亚洲第一综合网| 色和尚色视频在线看网站| 色www永久免费视频| 欧美中文字幕在线| 性一交一乱一乱一视频亚洲熟妇 | 高清国产精品一区二区| 五月色丁香婷婷网蜜臀av| 日韩插啊免费视频在线观看| 曰欧一片内射vα在线影院| 日本a天堂| av在线手机中文字幕| 偷拍综合在线视频二区| 欧美野外疯狂做受xxxx高潮| 在线观看一区二区女同| 少妇被啪出水在线视频| 亚洲日韩欧美一区、二区| 日本高清一区二区三区水蜜桃| 亚洲一区二区av偷偷| 国产精品一区二区三区卡| 国产呦系列呦交| 中文字幕乱码人妻无码久久久1 | 无码人妻av免费一区二区三区| 亚洲欧洲精品成人久久曰影片| 欧美人与动牲交片免费| 亚洲国产成人久久精品一区| 免费a级毛片无码|