今天看了一本關於vc++的書,上面將的是一些簡單的**,以前沒有注意以為很簡單,在家沒有事情可做,就對這些東西重新詳細的看了一邊,發現有一些問題是需要注意的,比如:指標。以前認為指標很少我能用上,但是現在才發現原來這個東西也是如此的好用,所以在網上找了一些資料,溫習一下。
**c/c++中的指標
在學習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、 指標的應用——傳遞引數。
#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]的內容,因此指標指向了乙個不確定的地方,由此產生的指標懸掛。example1()中,ax返回了正確的結果的位址。
4、 記憶體問題:使用指標注意記憶體的分配和邊界。
使用指標過程中應該給變數乙個適當的空間,以免產生不可見的錯誤。
請看以下**:
#include 「iostream.h」
void main()
char *a1;
char *a2;
cin >>a1;
cin >>a2;
cout <<」a1=」<
cout <<」a2=」<
} 輸入:abc
123
輸出:
a1=123
a2=
null pointer assignment
指標指向了「空」。解決辦法就是分配適當的記憶體給這兩個字串。修正後的**如下:
#include 「iostream.h」
void main()
char *a1;
char *a2;
a1=new char [10];
a2=new char [10];
cin >>a1;
cin >>a2;
cout <<」a1=」<
cout <<」a2=」<
delete(a1);注意,別忘了要釋放記憶體空間
delete(a2);
到此就能輸出正確的結果了。
分配了適當的記憶體之後要注意釋放內參空間,同時還應該注意不要超出所分配的記憶體的大小,否則會有溢位現象產生,導致不可預料的結果。
5、 關於特殊的指標——引用
引用有時候應用起來要比指標要靈活,用它做返回的時候是不產生任何變數的副本的這樣減小了記憶體的占用,提高執行的速度。引用使用起來要比指標好理解,比較直觀。當引用作為引數時,不會改變引數的位址,因此可以作為左值。
下面請看乙個例子:
#include 「iostream.h」
char ch[5]=」abcd」;
char &example(int b)
return ch;
void main()
cout <<」ch=」<
example(2)=」c」;
cout<<」ch=」<
} 輸出結果:
ch=abcd
ch=abcd
在實際程式設計過程中,可以靈活地引用或指標,盡量提高程式的可讀性和執行效率。
三、小結:
指標是學習c/c++的重點難點,主要原因是指標較為抽象,不容易理解。使用指標千萬要明白讓指標指向什麼地方,如何讓指標指向正確的地方。在深入系統底層之中需要應用到大量的指標,因此需要理解好指標的基本概念,例如:指標型別和指標所指向的型別。平時應該對留心觀察,了解程式的工作過程,必要時候可以對程式進行反彙編,加深對指標的理解,這種方法同樣適合學別的程式設計方面的知識。
四、結束:
指標的應用是很廣泛的,利用指標可以做很多事情,要成為乙個好的程式設計師,必須對指標有比較深刻的了解。寫本文的目的在於讓大家對指標有更深一層的了解,提高指標的應用能力,內容大都是我在實際程式設計中遇到的問題。相信能給大家一定的幫助。
以上是網上查詢的東西,寫的不錯,好好看看!
C 學習筆記 四 指標 4
類成員指標 本文主要討論 c 中類成員的指標,這部分內容少有使用,也比較難於理解。如果文中有錯誤或遺漏之處,敬請指出,謝謝!需要使用類成員指標的情況是比較少見的,所以一般沒人使用這個語言特性。下面先介紹類成員指標的使用方法,再介紹它的可能應用場合。有時,我們需要在類外的其它地方直接獲得類成員,這時我...
C 學習筆記 四 指標 1
函式存放在記憶體的 區域內,它們同樣有位址,我們如何能獲得函式的位址呢?如果我們有乙個int test int a 的函式,那麼,它的位址就是函式的名字,這一點如同陣列一樣,陣列的名字就是陣列的起始位址。定義乙個指向函式的指標用如下的形式,以上面的test 為例 int fp int a 這裡就定義...
C語言學習筆記(四) 指標
c語言學習筆記 四 指標 include intmain p就是乙個指標,p就是取出p指向位址的值 陣列 相同型別的資料集合 include intmain 在這個程式中,p是乙個指標,a是乙個陣列,若p a 0 或者p a就是p指向陣列的第乙個元素,接下來就可以對p進行 1或 1進行偏移操作 in...