指針是c/c++學習一個比較讓人頭痛的問題,在程序設計過程中,指針也往往是產生隱含bug的原因。下面就來 談談指針的應用以及需要注意的一些問題,里面也許就有你平時沒有注意到的問題,希望能幫 助各位讀者理解好指針。 一、我們先來回憶一下指針的概念吧,方便下面的介紹 指針是存放地址值的變量或者常量。例如:int a=1;&a就表示指針常量(“&”表示 取地址運算符,也即引用)。int *b,b表示的是指針變量(注意,是b表示指針變量而 不是*b),*表示要說明的是指針變量。大家注意int *b[2]和int(*b)[2]是不同的, int *b表示一個指針數組,而int (*b)[2]表示含有兩個元素的int指針,這里要注意 運算優先級問題,有助于理解指針問題。 在這里大概介紹基本概念就夠了,至于具體使用方法,如賦值等,很多書都有介紹 ,我就不多說了。 二、應用以及注意的問題 1、 理解指針的關鍵所在——對指針類型和指針所指向的類型的理解 ①、 指針類型:可以把指針名字去掉,剩下的就是這個指針 例如:int *a;//指針類型為int * int **a;//指針類型為int ** int *(*a)[8];//指針類型為 int *(*)[8] ②、 指針所指向的類型:是指編譯器將把那一片內存所看待成的類型。這里只要把 指針聲明語句中的指針名字和名字右邊的“*”號去掉就可以了,剩下的就是指針所指向 的類型。 我之所以把他們放在第一位,是因為弄清楚他們是學c/c++指針的重點,正確理解他 們才能使你打好c/c++的編程基礎。 2、 指針的應用——傳遞參數。 其實它可以相當于隱式的返回值,這就比return的方法更加靈活了,可以返回更多 的值,看看下面的例子自然就明白了: #include "iostream.h" void example(int *a1,int &b1,int c1) { *a1*=3; ++b1; ++c1; } void main() { int *a; int b,c; *a=6; b=7;c=10; example(a,b,c); cout 《"*a="《*a< cout 《"b="< cout 《"c="< }
輸出:*a=18 b=8 c=10 注意到沒有,*a和b的值都改變了,而c沒有變。這是由于a1是指向*a(=6)的指針 ,也即與a是指向同一個地址,所以當a1指向的值改變了,*a的值也就改變了。在函數中 的參數使用了引用(int &b1),b1是b的別名,也可以把它當作特殊的指針來理解,所 以b的值會改變。函數中的參數int c1只是在函數中起作用,當函數結束時候便消失了, 所以在main()中不起作用。 3、 關于全局變量和局部變量的一個問題 先不廢話了,先看看程序: #include “iostream.h” int a=5; int *example1(int b) { a+=b; return &a; } int *example2(int b) { int c=5; b+=c; return &b; } void main() { int *a1=example1(10); int *b1=example2(10); cout 《”a1=”《*a1< cout 《”b1=”《*b1< } 輸出結果: a1=15 b1=4135 *b1怎么會是4135,而不是15呢?是程序的問題?沒錯吧? 由于a是全局變量,存放在全局變量的內存區,它一直是存在的;而局部變量則是存 在于函數的棧區,當函數example2()調用結束后便消失,是b指向了一個不確定的區域 ,產生指針懸掛。 下面是對example1()和example2()的反匯編(用TC++ 3.0編譯):
example1(): push bp;入棧 mov bp,sp mov ax,[bp+04];傳遞參數 add [00AA],ax;相加 mov ax,00AA ;返回了結果所在的地址 pop bp;恢復棧,出棧 ret;退出函數 example2(): push bp;入棧 mov bp,sp sub sp,02 mov word ptr [bp-02],0005 mov ax,[bp-02];傳遞參數 add [bp+04],ax;相加 lea ax,[bp+04];問題就出在這里 mov sp,bp pop bp;恢復棧,出棧 ret;退出函數 對比之后看出來了吧?ax應該是存儲的是結果的地址。而在example2()中,返回 的卻是[bp+04]的內容,因此指針指向了一個不確定的地方,由此產生的指針懸掛。exa mple1()中,ax返回了正確的結果的地址。 4、 內存問題:使用指針注意內存的分配和邊界。 使用指針過程中應該給變量一個適當的空間,以免產生不可見的錯誤。 請看以下代碼: #include “iostream.h” void main() { char *a1; char *a2; cin 》a1; cin 》a2; cout 《”a1=”< cout 《”a2=”< }
|