c語言常常讓人覺得它所能表達的東西非常有限。它不具有類似第一級函式和模式匹配這樣的高階功能。但是c非常簡單,並且仍然有一些非常有用的語法技巧和功能,只是沒有多少人知道罷了。
指定的初始化
很多人都知道像這樣來靜態地初始化陣列:
int fibs = ;
c99標準實際上支援一種更為直觀簡單的方式來初始化各種不同的集合類資料(如:結構體,聯合體和陣列)。
陣列
我們可以指定陣列的元素來進行初始化。這非常有用,特別是當我們需要根據一組#define來保持某種對映關係的同步更新時。來看看一組錯誤碼的定義,如:
/*entries may not correspond to actual numbers. some entries omitted.
*/#define einval 1
#define enomem 2
#define efault 3
/*...
*/#define e2big 7
#define ebusy 8
/*...
*/#define echild 12
/*...
*/
現在,假設我們想為每個錯誤碼提供乙個錯誤描述的字串。為了確保陣列保持了最新的定義,無論標頭檔案做了任何修改或增補,我們都可以用這個陣列指定的語法。
char *err_strings =;
這樣就可以靜態分配足夠的空間,且保證最大的索引是合法的,同時將特殊的索引初始化為指定的值,並將剩下的索引初始化為0。
巨集列表
c中的乙個慣用方法,是說有乙個已命名的實體列表,需要為它們中的每乙個建立函式,將它們中的每乙個初始化,並在不同的**模組中擴充套件它們的名字。這在 mozilla的原始碼中經常用到,我就是在那時學到這個技巧的。例如,在我去年夏天工作的那個專案中,我們有乙個針對每個命令進行標記的巨集列表。其工作方 式如下:
#define flag_list(_) \_(inworklist) \_(emittedatuses) \
_(loopinvariant) \
_(commutative) \
_(movable) \
_(lowered) \
_(guard)
它定義了乙個flag_list巨集,這個巨集有乙個引數稱之為 _ ,這個引數本身是乙個巨集,它能夠呼叫列表中的每個引數。舉乙個實際使用的例子可能更能直觀地說明問題。假設我們定義了乙個巨集define_flag,如:
#define define_flag(flag) flag,enum
flag ;
#undef define_flag
對flag_list(define_flag)做擴充套件能夠得到如下**:
enumflag ;
接著,對每個引數都擴充套件define_flag巨集,這樣我們就得到了enum如下:
enumflag ;
接著,我們可能要定義一些訪問函式,這樣才能更好的使用flag列表:
#define flag_accessor(flag) \bool
is##flag() const
\void
set##flag() \
void
setnot##flag()
flag_list(flag_accessor)
#undef flag_accessor
一步步的展示其過程是非常有啟發性的,如果對它的使用還有不解,可以花一些時間在gcc –e上。
C語言 實用除錯技巧
如何寫出好 易於除錯 的 程式設計常見的錯誤 debug 通常稱為除錯版本,它包含除錯資訊,並且不作任何優化,便於程式設計師除錯程式。release 稱為發布版本,它往往是進行了各種優化,使得程式在 大小和執行速度上都是最優的,以便使用者很好地使用。int main printf p n arr p...
C 實用小技巧
系統自帶全球唯一標示id system.guid.newguid tostring 字元竄或者變數前加乙個 標示為路徑 muban.doc 複製檔案 system.io.file.copy 檔案路徑,檔案路徑 刪除檔案 system.io.file.delete 檔案路徑 結束程序 foreach ...
C 實用技巧(二)
上一篇文章講到了如何檢查記憶體洩露。其實只要肯用c 的stl裡面的高階功能的話,記憶體洩露是很容易避免的。我在開發vczh library 3.0的時候,所有的測試用例都保證跑完了沒有記憶體洩露。但是很可惜有些c 團隊不能使用異常,更甚者不允許寫建構函式析構函式之類,前乙個還好,後乙個簡直就是在用c...