新手學習之淺析一下c/c++中的指針

1、咱們先來回憶一下指針的概念吧,方便下面的介紹
  

  指針是存放地址值的變量或者常量。例如:int a=1;&a就表示指針常量(「&」表示取地址運算符,也即引用)。int *b,b表示的是指針變量(注意,是b表示指針變量而不是*b),*表示要說明的是指針變量。你們注意int *b[2]和int(*b)[2]是不一樣的,int *b表示一個指針數組,而int (*b)[2]表示含有兩個元素的int指針,這裏要注意運算優先級問題,有助於理解指針問題。在這裏大概介紹基本概念就夠了,至於具體使用方法,如賦值 等,不少書都有介紹,我就很少說了。
  
  2、應用以及注意的問題
  

  一、 理解指針的關鍵所在——對指針類型和指針所指向的類型的理解
  
  ①、 指針類型:能夠把指針名字去掉,剩下的就是這個指針
  
  例如:int *a;//指針類型爲int *
  
  int **a;//指針類型爲int **
  
  int *(*a)[8];//指針類型爲 int *(*)[8]
  
  ②、 指針所指向的類型:是指編譯器將把那一片內存所看待成的類型。這裏只要把
  
  指針聲明語句中的指針名字和名字右邊的「*」號去掉就能夠了,剩下的就是指針所指向的類型。
  
  我之因此把他們放在第一位,是由於弄清楚他們是學c/c++指針的重點,正確理解他們才能使你打好c/c++的編程基礎。
  
  二、 指針的應用——傳遞參數。
  
  其實它能夠至關於隱式的返回值,這就比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()中不起做用。
  
  三、 關於全局變量和局部變量的一個問題先不廢話了,先看看程序:
  #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返回了正確的結果的地址。四、 內存問題:使用指針注意內存的分配和邊界。使用指針過程當中應該給變量一個適當的空間,以避免產生不可見的錯誤。請看如下代碼:
  #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);
  }
  
  到此就能輸出正確的結果了。分配了適當的內存以後要注意釋放內參空間,同時還應該注意不要超出所分配的內存的大小,不然會有溢出現象產生,致使不可預料的結果。
  
   五、 關於特殊的指針——引用
  
  引用有時候應用起來要比指針要靈活,用它作返回的時候是不產生任何變量的副本的這樣減少了內存的佔用,提升執行的速度。引用使用起來要比指針好理解,比較直觀。當引用做爲參數時,不會改變參數的地址,所以能夠做爲左值。
  
  下面請看一個例子:
  #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
  
  在實際編程過程當中,能夠靈活地引用或指針,儘可能提升程序的可讀性和執行效率。
  
  3、小結:
  
   指針是學習c/c++的重點難點,主要緣由是指針較爲抽象,不容易理解。使用指針千萬要明白讓指針指向什麼地方,如何讓指針指向正確的地方。在深刻系統 底層之中須要應用到大量的指針,所以須要理解好指針的基本概念,例如:指針類型和指針所指向的類型。平時應該對留心觀察,瞭解程序的工做過程,必要時候可 以對程序進行反彙編,加深對指針的理解,這種方法一樣適合學別的編程方面的知識。
  
  4、結束:
  
  指針的應用是很普遍的,利用指針能夠作不少事情,要成爲一個好的程序員,必須對指針有比較深入的瞭解。寫本文的目的在於讓你們對指針有更深一層的瞭解,提升指針的應用能力,內容大都是我在實際編程中遇到的問題。相信能給你們必定的幫助。ios

相關文章
相關標籤/搜索