1. 命名習慣
#define pi 3.1415926
int min_value, max_value;
void send_data(void);
變數名,函式名全都小寫,單詞之間用「_」連線。
2. case範圍
gnu c支援case x...y這樣的語法,區間[x,y]的數都會滿足這個case的條件,例如:
swith(ch)
**中的case '0'...'9'等價於標準c中的如下**:
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
3. 語句表示式
gnu c把包含在括號中的復合語句看作是乙個表示式,稱為語句表示式,它可以出現在任何允許表示式的地方。我們可以在語句表示式中使用原本只能在符合語句中使用的迴圈變數、區域性變數等,例如:
#define min_t(type,x,y) \
()int ia, ib, mini;
float fa, fb, minf;
mini = min_t(int, ia, ib);
minf = min_t(float, fa, fb);
因為重新定義了__x和__y這兩個區域性變數,所以以上述方式定義的巨集不會有***。在標準c中,對應的如下巨集則會產生***:
#define min(x,y) ((x) < (y) ? (x) : (y))
**min(++ia, ++ib)會被展開為((++ia)<(++ib)?(++ia):(++ib)), 傳入巨集的引數被增加了兩次。
4. typeof關鍵字
typeof(x)語句可以獲得x的型別,因此,我們可以借助typeof重新定義min這個巨集:
#define min(x,y) ()
我們不需要像min_t(type,x,y)這個巨集那樣把type傳入,因為通過typeof(x)、typeof(y)可以獲得type。**行(void)(&_x==&_y)的作用是檢查_x和_y的型別是否一致。
5. 可變引數的巨集
標準c只支援可變引數的函式,意味著函式的引數是不固定的,例如printf()函式的原型為:
int printf( const char *format [, argument]... );
而在gnu c中,紅葉可以接受可變數目的引數,例如:
#define pr_debug(fmt,arg...) \
printk(fmt,##arg)
這裡arg表示其餘的引數可以是零個或多個,這些引數以及引數之間的逗號構成arg的值,在巨集擴充套件時替換arg,例如下列**:
pr_debug("%s:%d",filename,line)
會被擴充套件成為:
printk("%s:%d", filename, line)
使用##的原因是處理arg不代表任何引數的情況,這時候,前面的逗號就變得多餘了。使用「##」之後,gnu c預處理器會丟棄前面的逗號。這樣,**:
pr_debug("success!\n")
會被正確的擴充套件為:
printk("success!\n")
而不是:
printk("success!\n",)
6. 當前函式名
gnu c預定義了兩個識別符號儲存當前函式的名字,__function__儲存函式在原始碼中的名字,__pretty_function__儲存帶語言特色的名字。在c函式中,這兩個名字是相同的。
void example()
**中的__function__意味著字串「example"。
7. do{} while(0)
在linux核心中,經常會看到 do{} while(0)這樣的語句,許多人開始都會疑惑,認為do{} while(0)毫無意義,因為它只會執行一次,加不加do{}while(0)效果完全一樣的,其實do{}while(0)主要用於巨集定義中。
這裡用乙個簡單的巨集來演示:
#define safe_free(p) do while(0)
假設這裡去掉do...while(0),即定義為:
#define safe_free(p) free(p); p = null;
那麼以下**:
if(null != p)
safe_delete(p)
else
...//do something
會被展開為:
if(null != p)
free(p); p = null;
else
...//do something
展開的**存在兩個問題:
(1)if分支後有兩個語句,導致else分支沒有對應的if,編譯失敗;
(2)假設沒有else分支,則safe_free中的第二個語句無論if測試是否通過都會執行。
將safe_free定義加上{}就可以解決上述問題了,即:
#define safe_free(p)
這樣,**:
if(null != p)
safe_delete(p)
else
...//do something
會被展開為:
if(null != p)
else
...//do something
但是,在c程式中,每個語句後面加乙個分號是一種約定俗成的習慣,那麼,如下**:
if(null != p)
safe_delete(p);
else
...//do something
將被擴充套件為:
if(null != p)
;else
...//do something
這樣,else分支就又沒有對應的if了,編譯將無法通過。假設用了do{} while(0),情況就不一樣了,同樣的**會被展開為:
if(null != p)
do while(0);
else
...//do something
不會再出現編譯問題。 do{}while(0)的使用完全就是為了保證巨集定義的使用者能無編譯錯誤的使用巨集,它不對其使用者做任何假設。 linux下的C 程式設計
第一步,要安裝c 的編譯器g 使用如下命令 root wl ms 7673 home wl 桌面 c apt get install g 第二步,開始我們的hello world 使用vim建立helloworld.cpp,輸入如下 root wl ms 7673 home wl 桌面 c cat ...
Linux下的C程式設計
linux下的c程式設計 學習內容 源程式編譯 makefile的編寫 程式庫的鏈結 程式的除錯 標頭檔案和系統求助 1.源程式的編譯 在linux下面,如果要編譯乙個c語言源程式,我們要使用gnu的gcc編譯器.下面我們以乙個例項來說明如何使用gcc編譯器.假設我們有下面乙個非常簡單的源程式 he...
linux下c 程式設計
yum install gcc c 安裝c 環境 然後開始編寫c 程式,假設放到test1.cpp中,g o test11 test1.cpp就會編譯test1.cpp生成test11檔案。test11就可以執行該程式 查詢乙個包是否被安裝 rpm q rpm package name 列出所有被安...