日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

为何不精通C? 03 深入剖析声明

發布時間:2023/12/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为何不精通C? 03 深入剖析声明 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??? 對于復雜的C函數聲明,或者被typedef別名后的聲明,很多人往往一頭霧水。本文主要解析下C語言中聲明過程所遵循的原則。

聲明

??? 引用《C專家編程》的第三章內容,說明下聲明的優先級規則:

  • 聲明從它的名字開始讀,然后按照優先級順序依次讀取。
  • 優先級從高到底依次為:
    • ?括號包圍的地方
    • 后綴操作符:
      • 括號()表示是一個函數
      • 方括號[]表示是一個數組
    • 前綴操作符:星號*表示類型是 指向....的指針
  • 若const/volatile關鍵字的后面緊跟類型說明符(int,float),那么其作用于類型,在其他情況下,作用于其左邊緊鄰的指針星號。
  • 不過,我覺得這個規則的不夠通俗,看了《C++Annotation》中關于const的那一章節,也詳細解釋了下這個規則,高效,庖丁解牛般分析:

    // 例子
    char* const *(*next)();
  • 從變量名開始
  • 往右看,直到聲明結束或碰到 ')'
  • 回到上一次開始的地方,往左看,直到直到碰到 ‘(’ 或到聲明開始的地方。
  • 若碰到(, 從2開始,整個被()包含的地方為一個成分,根據語境解釋其含義
  • 到開頭結束
  • 通俗的乒乓解釋,就是從變量名開始,碰到)或結束往左讀,碰到(往右讀。

    遇到*()[]解釋之

    其中 解釋是函數的話,需解釋其形參表返回值

    ?????? 解釋為數組的話,需解釋數組元素是什么

    ?????? 解釋為指針時,需解釋其指向什么類型

    舉例:

    1 next 名叫next, 開始往右讀,碰到了),折向往左 2 (*next) 遇到* ,解釋是一個指針 繼續往左讀碰到(, 折向往右 3 (*next)() 遇到(),解釋指向一個函數,該函數沒有形參 到末尾,折向往左
    4 *(*next)() 遇到*,解釋函數返回一個指針,關于函數的形參表和返回值解釋完畢 , 繼續往左 5 char* const *(*next)() 先碰到const,再是*, 最后是char, 解釋函數的返回值(指針)指向一個char型指針常量,即指針不可賦新值,所指的值可以改變。到開頭,結束。

    以上的例子是函數的聲明舉例。

    對其他的聲明也是一樣的,比如之前文章中? int *ap[], 我們也是這樣解釋的:

    • 從 ap 開始往右讀,碰到了[], 說明是一個數組
    • 然后到末尾,折向向左,碰到*,說明數組的元素是指針,
    • 最后碰到int,說明該元素的指針類型為 int*

    常規的 const int * p; 也可以這么來:

    • 從 p 開始,結尾折向,往左走。
    • 先碰到*, 說明是一個指針
    • 再碰到 int,const, const修飾的是int, 則說明該指針指向一個const int東西

    同理,對于 int* const p: 我們在往左看時,先看到了const,再*, 說明const修飾的是*。

    來個復雜的挑戰下吧:

    char* const* (* const (*(*ip)() ) [] ) [] (*ip) ip是一個指針 (*ip)() ip是一個函數指針,該函數無形參 *(*ip)() 函數返回一個指針 (...)[] 該指針指向一個數組 *const (...)[] 數組元素為 常量指針 (*const (...)[]) [] 該常量指針指向一個數組 char* const* {...}該數組內元素為指向char型常量指針的指針 合起來就是:ip是一個函數指針(無形參), 返回一個指向數組的指針,該數組內元素為常量指針,其指向一個元素為char型常量指針的數組。

    不過,一般不會有這種聲明來惡心我們的。。我們基本上知道怎么打乒乓就行了。


    typedef

    剖析完了聲明,一般來說還要說下 typedef ,這可是C的一大神器呀。

    首先,我們要明確的是,typedef是為類型創建別名,而不是創造新的類型。

    講typedef時,又必須和 #define做下區分, define僅是簡單的宏擴展

    主要來說,有以下的區別:

    • 首先,可以對其他類型說明符采用宏類型名進行擴展,但對typedef所定義則不行
    #define INT int typedef int tInt unsigned INT ci; // 正確,類型為unsigned int unsigned tInt tci; // 非法,錯誤
    • 其次,連續變量聲明中,typedef能夠保證所有定義類型一致,而#define不能保證
    #define pD int* typedef int* pT pD a,b; // a類型為 int*, b類型為int pT c,d; // c,d類型均為int*

    和typedef做好朋友

    void (*signal(int sig, void(*func)(int))) (int);

    我們來分析下這個是什么東西:

    ??? signal(..) : signal 是一個函數,有復雜的形參表

    ??? *signal(...) : 返回值是一個指針

    ??? void {*}(int) : 該指針指向一個函數,該函數的形參為int, 這個函數的返回值是void

    我們看看signal的形參表: 兩個參數,一個參數是 int; 另外個參數 void(*func)(int) 是一個函數指針,該函數有一個int形參,返回void;

    對比下,我們可以分析出, signal的返回值和 func的定義一樣, 都是 void(*)(int), 但若是采用這種寫法的話,不好看懂,這時候,我們的好朋友typedef就出現了:

    typedef void(*ptr_to_func)(int); ptr_to_func signal(int, ptr_to_func){.....}

    另外,typedef也經常和struct配合使用。

    typedef struct my_struct{....} NewName;

    這樣,NewName 就等同于 struct my_struct , 少打了struct這幾個字符


    擴展說下 聲明和定義的區別:

    C語言中,對象有且僅有一個定義,而聲明卻可以有多個extern 聲明。

    定義:只能出現在一個地方,確定同時分配內存,它是特殊的聲明

    聲明:只是描述其他地方創建對象的屬性。有extern前綴,作用于變量

    具體的一些擴展區別,見后續博文,關于指針和數組的闡釋

    END

    要點: 怎么打乒乓?typedef是個別名好朋友

    轉載于:https://www.cnblogs.com/IntellX/archive/2013/05/17/3083701.html

    總結

    以上是生活随笔為你收集整理的为何不精通C? 03 深入剖析声明的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。