c指標解讀之左右法則(轉自:http://blog.csdn.net/cattycat/article/details/5660353#quote)

來源:互聯網
上載者:User

C指標聲明解讀之左右法則
C語言所有複雜的指標聲明,都是由各種聲明嵌套構成的。如何解讀複雜指標聲明呢?右左法則是一個既著名又常用的方法。不過,右左法則其實並不是C標準裡面的內容,它是從C標準的聲明規定中歸納出來的方法。C標準的聲明規則,是用來解決如何建立聲明的,而右左法則是用來解決如何辯識一個聲明的,兩者可以說是相反的。右左法則的英文原文是這樣說的:
  The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till
the whole declaration has been parsed.  

這段英文的翻譯如下:

  右左法則:首先從最裡面的圓括弧內未定義的標識符開始閱讀看起,然後往右看,再往左看。每當遇到圓括弧時,就應該掉轉閱讀方向。一旦解析完圓括弧裡面所有的東西,就跳出圓括弧。重複這個過程直到整個聲明解析完畢。

  總之對聲明進行分析,最根本的方法還是按優先順序和結合性來類比替換,從那些最基本的聲明進行類比,簡化,從而進行理解。下面分析幾個例子,來具體闡述如何使用這種方法。

#1:int* (*a[5])(int, char*);

  首先看到標識符名a,"[]"優先順序大於"*",a與"[5]"先結合。所以a是一個數組,這個數組有5個元素,每一個元素都是一個指標,指標指向"int* (int, char*)",很明顯,指向的是一個函數,這個函數參數是"int, char*",傳回值是"int*"。OK,結束了一個。:)

#2:void (*b[10]) (void (*)());

  b是一個數組,這個數組有10個元素,每一個元素都是一個指標,指標指向一個函數,函數參數是"void (*)()"【注:這也是一個函數指標, 參數為空白,返回為void】,傳回值是"void"。完畢!

#3:int(*)() (*c)[9];

   c是一個指標,指標指向一個數組,這個數組有9個元素,每一個元素都是"int(*)()"(也即一個函數指標,指向一個函數,這個函數的參數為空白,傳回值是int型)。

#4:int (*(*d)[5])(int *);

  (*d)------指標;
  (*d)[5]------這個指標指向一個數組;
  *(*d)[5]------這個數組中每個元素都是指標類型;
  int (int *)------ 什麼類型的指標?這個類型的。
    
    
#5:int (*(*e)(int *))[5];  
  *e-----向右遇到括弧,向左遇到*,說明e是個指標,啥指標呢?
  (*e)(int *)------跳出括弧向右遇到(int *),說明這個指標是個函數指標,形參為int*, 傳回值為何?且聽下回分解:);
  *(*e)(int *)------傳回值為何?向右遇到括弧,再向左,喔,遇到*了,那就是返回了一個指標了。啥指標呢? 同樣地,下回分解;
  (*(*e)(int *))[5]-------向右遇到[],說明那是個指向數組的指標,是啥數組呢?不急,慢慢來;
  int (*(*e)(int *))[5]-------向左遇到int,喔,明白了,就是個簡單的整型數組。OVER

    
  當然實際當中,當需要聲明一個複雜指標時,如果把整個聲明寫成上面所示的形式,對程式可讀性將是一個巨大損害。誰要是寫出這樣BT的指標聲明,那就真是丟rp了,估計會被罵死!。
  還是用typedef來對聲明逐層分解替換下吧,增強可讀性。

  例如對於上面的聲明:int (*(*func)(int *))[5]; 可以這樣分解:
  typedef int (*pArr)[5];  
  typedef pArr (*func)(int *);  
  這樣就容易讀得多了啊!

  再看看這個啥意思? typedef int (* (* (*FUNC)(int *) )[5] )(int *); ---- 暈了吧。

  其實typedef int (* (* (*FUNC)(int *) )[5] )(int *);  
  等價與下面的:)

  typedef int (*PF)(int *);

  typedef PF (*PARRAY)[5];

  typedef PARRAY (*FUNC)(int *);

  (*(void (*)())0)();------->這個呢?
  按左右法則:
  (void (*)()) -----是一個傳回值為void,參數為空白的函數指標原型。
  (void (*)())0-----把0強轉成一個傳回值為void,參數為空白的函數指標,指標指向的地址為0.
  *(void (*)())0-----前面加上*表示整個是一個傳回值為void的函數的名字
  (*(void (*)())0)()------這當然就是一個函數調用了。

  再typedef化簡下:
  typedef void (*pf)();
  (*(pf)0)();

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.