999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

淺談C語言中的指針

2008-12-31 00:00:00張琳梅尚永強
電腦知識與技術 2008年35期

摘要:指針是C語言的一個重要概念,文章對指針基本概念和使用作了簡單介紹,總結了指針在使用過程中常犯的錯誤,討論了出錯的原因,指出正確使用指針的方法,并闡述了C語言中的指針與數組、函數等結合起來的指針及其應用。

關鍵詞:C語言;指針;數組;函數

中圖分類號:TP312文獻標識碼:A文章編號:1009-3044(2008)35-2546-04

On the Pointer in the Language \"C\"

ZHANG Lin-mei1, SHANG Yong-qiang2

(1.Computer Science Department, Xinyang Agriculture College, Xinyang 464000 ,China; 2.Administration Office, Xinyang Agriculture College, Xinyang 464000 ,China)

Abstract: C language pointer is an important concept,This article made a brief introduction on the basic concept and use of pointer, summed up mistakes of the pointer used in the process,discussed the causes of the problem,pointed out the proper use of the pointer approach,and elaborated on the array of pointers in the C language, such as combining the functions of the pointer and its application.

Key words: C language; pointer; arrays; function

1 引言

C語言是使用最廣泛的程序設計語言之一,它以功能強大,語言簡練,編程靈活等特點為廣大程序設計人員所青睞,但對初學者是有一定難度的。尤其是指針,它既是C語言的一個重要特色,又是C語言的重點和難點。正確而靈活的使用指針,可有效的表示復雜的數據結構、動態分配空間、方便引用字符串和數組、在函數調用中獲得多個返回值、并且可以直接處理內存地址等等。正是因為指針太靈活,一旦指針使用不當,將會導致程序出錯,甚至造成系統崩潰。因此,要編寫出正確高效的程序,正確理解和使用指針,以及了解指針使用的常見錯誤是很有必要的。

2 指針的理解和使用

2.1 指針的理解

理解語言指針的基礎就是牢固樹立指針就是地址的概念。明確地說,指針常量就是地址常量,指針變量就是地址變量。

我們先來看看指針常量:

1) 若a是整型常量,則a表示是a的地址,因為常量的地址在內存中是固定的,因此,是a指針常量。

2) 對于數組來說,只寫數組名表示數組的首地址,而數組在內存中的位置是不能改變的,所以它也是指針常量。

3) 對于字符串常量來說,直接寫出某一字符串就是表示是該字符串的首地址,這是許多教科書上未能提到的。字符串常量在內存中有固定的位置,字符串常量的地址也屬于指針常量。

4) 對于某個函數來說,它在內存中的地址也是固定的。這樣,函數的地址也屬指針常量,在C語言中,函數名可以表示函數的地址。

再來看看指針變量:

指針變量就是地址變量,就是說,它是用來存放某一類變量地址的變量。有此概念以后,我們就容易理解指針數組的元素是用來存放變量地址的。同樣,在處理鏈表、二叉樹這類遞歸數據結構時,相應的結構中應存放其它結點的地址從而形成鏈接的成員變量,即該成員變量應是地址變量,必須用指針變量來刻畫。

對于指針變量來說,C語言提供了“ * ” 運算符,它表示取該變量的內容,而當指針變量是指向某一函數時,這時的“ 取內容” ,應廣義的理解,即執行相應的函數。

2.2 指針的使用

在程序中定義一個變量,C語言編譯系統就會根據該變量的數據類型,為其分配相應的存儲單元,類型不同所分配的存儲單元的字節數也是不同的。指針變量是一種特殊類型的變量,定義一個指針類型后,C語言編譯系統便會為該指針變量分配一個存儲單元,用于存放相應變量的地址。使用該指針變量時,必須保證該指針變量指向一個明確的存儲單元,即被賦值。例如:

int *p,i=2;

p=i;

使用指針時,常常涉及到兩個運算符:

1) :獲取存儲單元的地址

2) *:獲取指針變量所指向的存儲單元的內容

例如,i表示變量i的地址,*p表示指針變量p所指向的存儲單元的內容,即變量i的內容為2。

2.3 指針變量的類型

指針變量與一般變量一樣,也有類型。指針變量的類型是指針所指向的數據的類型,我們也稱指針變量類型為指針變量的基類型。指針變量的基類型不僅僅是指所定義指針變量的類型修飾符,同時還包含該指針變量是對多大的存儲空間進行解釋。例如:

int *p1,(*p2)[3],(*p3)[2][3];

其中,p1可指向1個int 型的存儲單元,p2可指向3個int型的存儲單元,p3可指向6個

int型的存儲單元。因此,p1+1是p1指針向下移動2個字節(基本整型占用2個字節),p2+1是p2指針向下移動6個字節(p2指向3個int型的存儲單元,每個存儲單元占用2個字節,即3×2),p3+1是p3指針向下移動12個字節(p3指向6個int型的存儲單元,每個存儲單元占用2個字節,即6×2)。

我們知道可以有下列語句定義指針與數組:

int * p ; / * 指向整型的指針* /

int a[3] ; / * 整型數組* /

那么把兩者結合起來會怎么樣呢?

int * pa[3] ;

是定義成數組呢?還是定義成指針呢?回答這個問題的關鍵在于運算符的優先級。因[ ]的優先級高于* ,加上括弧后定義變成

int ( * (pa[3]) ) ;

所以pa究竟定義成什么,只要從內層依次往外層看就可以了。即pa是數組,由三個元素組成,每個元素是指針,是指向int 型的指針。綜合起來,pa是由三個指向int型的指針所構成的數組。

所以對于一個復雜的定義,我們可以按以下步驟來理解它:

1) 根據優先次序,加上必要的括弧,使變量名在最內層。

2) 從最內層開始依次往外層看,寫上所看到的內容。

如: * —→指向×××的指針

[ n] —→有n 個元素的數組

() —→返回×××的函數等等

例如,對于int * * pp ;

1) 加括弧int ( * ( * pp) ) ;

2) pp 是指針,是指向指針的指針,該指針是指向int 型的。

3) 所以,pp 是指向int 型指針的指針。

注意,這時不要被兩個* 所困惑。pp 也只不過是一個指針變量而已。請看下面的操作: 如圖1:

int i ;

int * p ;

int * * pp ;

pp = p ; / * 把指向int 型的指針變量p 的地址放入pp 所在的內存單元* /

p = i ; / * 把int 型變量i 的地址放入p 所在的內存單元* /

* * pp = 2 ; / * 把整數2 放入變量i 所在的內存單元* /

圖1

現在我們知道,編繹系統不能區分簡單指針和指向數組元素的指針。換句話說,對指針進行操作的時候,對指針指向的具體對象不能加以區分。如上面的pp 是指向一個int 型的指針變量的,而在下面的例子中,pp就指向了一個指針數組。如圖2:

int a[3] ;

int * pa[3] ;

int i0 ,i1 ;

int * * pp ;

pp = pa ;

pa[0] = i0 ;

pa[1] = i1 ;

pa[2] = a ;

* * (pp + 1) = 5 ;

* ( * (pp + 2) + 2) = 6 ;

圖2

當然還有pp 指向其它對象的可能。所以定義了1個指針以后,要記住它究竟是指向一個簡單的對象呢?還是指向數組?這就要由編程序者自己掌握了。

再看下面的例子:

int ( * pa) [3] :

按我們先前介紹的方法去理解,可知pa是一個指向由三個整型元素組成的數組的指針,通過下面的語句可以對它進行初始化。如圖3:

int ( * pa) [3] ;

int a[ 3] ;

pa = a ;

* * pa = 7 ;

( * pa) [1] = 8 ;

* ( * pa + 2) = 9 ;

圖3

3 指針使用中常見的錯誤

指針類型有其獨特的特點,正確合理的使用可以提高程序的功能,但錯誤地理解和使用指針,將導致無法想象的結果。下面分析討論指針使用中常犯的錯誤。

3.1 指針變量未賦值

指針變量在使用之前必須賦初值,這個初值應該是一個地址量。如果只是定義了一個指針變量而沒有為它賦值,此時,指針變量指向的是一個不明確的存儲單元。例如:

int *p;

*p=8; /* 錯誤 */

該例中,將10賦值給p指向的存儲單元,而p指向哪個存儲單元是不確定的。應該改為:

int a,*p;

p=a;

*p=8;

這樣指針p就指向了變量a,*p=10,實際上是將10賦值給變量a。或者也可以先調用C語言中的內存分配函數得到相應的存儲空間,再將函數返回的首地址賦值給指針變量。即:

int *p;

p=(int*)malloc(sizeof(int));

if(p!=NULL)

*p=8;

因此,對應指針變量一定要保證:先給指針變量賦值,然后再使用。

3.2 指針類型不匹配

在給指針變量賦值時,只能將與指針變量基類型相同的變量的地址賦值給改指針變量。例如:

int *pa,a;

float *pb,b;

pa=b;/* 錯誤 */

pb=a;/* 錯誤 */

例子中,指針pa的基類型為int型,指針pb的基類型為float型,只能將int型變量的地址賦值給pa,將float型變量的地址賦值給pb。應改為:

int *pa,a;

float *pb,b;

pa=a;

pb=b;

另外,基類型相同不僅僅是指類型相同,還包含系統分配給這種基類型的存儲單元的容量也相同。例如:

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

int *p1,(*p2)[3];

p1=a;/* 錯誤 */

此例中,p1=a是錯誤的,原因是p1與a的基類型是不同的,p1的基類型是含有1個int型的存儲單元,a是二維數組名,是地址常量,它總共有2行,每行3個元素,因此它的基類型是含有3個int型的存儲單元。其中,p2的基類型是含有3個int型的存儲單元,p2與a的基類型是相同的,因此可以把a賦值給p2,這樣就正確了。所以,在給指針變量賦值時,要考慮基類型是否匹配。

3.3 指針變量所指示的存儲單元越界

當指針變量對所指示的存儲單元進行操作時,應保證所操作的存儲單元應該是已分配給程序的存儲單元,不應該越界,否則將會導致嚴重的后果。例如:

main()

{int i,a[5],*p;

p=a;

for(i=0;i<5;i++)

*p++=i+1;

for(i=0;i<5;i++)

printf(“%d”,*p++);

}

第一個for循環用于給數組a的5個元素賦值,第二個for循環用于把數組a的5個元素輸出,看上去好像沒錯,但輸出的結果卻是出現了問題,程序中存在嚴重的錯誤,原因是程序開始p指向數組a的首地址,當第一個for循環執行結束時,p指向數組a的末尾,因此第二個for循環開始執行時,p指針的值并不是a[0],而是a+5,其值超過了系統給數組分配的空間,應該在第二個for循環前面加上一條語句:

p=a;

使p指針再重新指向a[0],這樣結果就正確了。

因此,在使用指針變量時,一定要注意指針變量應在系統所分配存儲空間使用,不要超過系統分配的空間范圍,否則結果是無法預料的。

3.4 指針函數帶回的指針不存在

函數的返回值不僅可以是一般的數據類型,還可以為指針類型,這種帶回的類型為指針的函數稱為指針函數。對于函數帶回的指針,這個指針所指示的存儲單元應該是存在的,不可以不存在。例如:

int *max(int x,int y)

{int *p;

if(x>y)p=x;

else p=y;

return p;

}

main()

{int a,b,*m;

scanf(“%d%d”,a,b);

m=max(a,b);

printf(“MAX=%d\”,*m);

}

max是指針函數,編寫該函數的本意是由指針P帶回x、y中較大數的地址,但函數max執行完畢,返回主函數main時x、y所占用的存儲單元已被釋放,而p帶回的將是一個不存在的存儲單元,這樣做顯然是不正確的。因此,程序應該改為:

int *max(int *x,int *y)

{int *p;

if(*x>*y)p=x;

else p=y;

return p;

}

main()

{int a,b,*m;

scanf(“%d%d”,a,b);

m=max(a,b);

printf(“MAX=%d\”,*m);

}

這樣修改后,max函數中的指針p帶回的則是主函數main中a、b中較大數的地址,就可以正確輸出了。可見指針函數中帶回的指針應該是主調函數中變量的地址,不能是已釋放空間的地址。

4 小結

指針是C語言的重要概念,是C語言的重要特色,它簡潔、靈活、高效,但又有風險。正確理解和使用指針,避免常見錯誤發生,不僅要小心謹慎,還有多編程,多上機調試,弄清細節,發現錯誤,積累經驗。

參考文獻:

[1] 譚浩強.C程序設計[M].北京:清華大學出版社,1999.

[2] 馮博琴等.C語言學習指南[M].北京:北京機械工業出版社,1996.

[3] 田淑清.全國計算機等級考試二級考試教程-C語言程序設計[M].北京:高等教育出版社,1998.

主站蜘蛛池模板: 国产69精品久久久久妇女| 国产99久久亚洲综合精品西瓜tv| 亚洲精品不卡午夜精品| 九九热免费在线视频| 91在线高清视频| 国产成人高清精品免费软件| 2020精品极品国产色在线观看 | 在线a网站| 国产黄在线免费观看| 国产精品免费电影| 日韩精品久久无码中文字幕色欲| 亚洲人成日本在线观看| 日韩天堂网| 久久久国产精品无码专区| 国产成人a毛片在线| 青青草国产免费国产| 一级黄色片网| 久久久久国产一级毛片高清板| 女高中生自慰污污网站| 中国特黄美女一级视频| 亚洲天堂网2014| 这里只有精品在线播放| 国产浮力第一页永久地址 | 99人体免费视频| 免费aa毛片| 在线毛片免费| 区国产精品搜索视频| 成人毛片免费观看| 波多野结衣一二三| 人人妻人人澡人人爽欧美一区| 国产96在线 | 亚洲无码91视频| 午夜小视频在线| 亚洲综合中文字幕国产精品欧美| 免费看美女自慰的网站| 91精品久久久无码中文字幕vr| 国产又粗又爽视频| 亚洲色欲色欲www网| 露脸一二三区国语对白| 国产高清毛片| 国产毛片高清一级国语| 亚洲一区免费看| 亚洲水蜜桃久久综合网站| 18禁影院亚洲专区| 亚洲色图另类| 午夜啪啪福利| 欧美一级夜夜爽www| 无码精品国产dvd在线观看9久| 91视频精品| 国产一区二区精品高清在线观看| 操操操综合网| 国产自在线播放| 国产精品冒白浆免费视频| 国产日本一区二区三区| 国产不卡国语在线| 老司国产精品视频91| 久久五月视频| A级全黄试看30分钟小视频| 91九色国产在线| 久久这里只有精品2| 国产农村精品一级毛片视频| 麻豆精品视频在线原创| 91亚洲国产视频| 亚洲高清在线天堂精品| 亚洲二三区| 国产成a人片在线播放| 99re经典视频在线| 午夜限制老子影院888| 欧美日韩国产在线人成app| 天天视频在线91频| 最新亚洲人成无码网站欣赏网| 中文字幕久久亚洲一区| 欧美中出一区二区| 久久久久久国产精品mv| 67194亚洲无码| a级高清毛片| 无码精油按摩潮喷在线播放| 欧美激情首页| 999国内精品久久免费视频| 在线国产91| 一本大道无码日韩精品影视| 色噜噜综合网|