c語言技巧

2021-06-21 03:10:03 字數 2560 閱讀 9428

c語言技巧

2012-12-22 16:43:49

分類: c/c++

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。

三、結構體與聯合體

用結構體與聯合體的欄位名稱來初始化資料是非常有用的。假設我們定義:

struct point

然後我們這樣初始化struct point:

struct point p =;

當我們不想將所有欄位都初始化為0時,這種作法可以很容易的在編譯時就生成結構體,而不需要專門呼叫乙個初始化函式。對聯合體來說,我們可以使用相同的辦法,只是我們只用初始化乙個字段。

四、編譯時斷言

這其實是使用c語言的巨集來實現的非常有「創意」的乙個功能。有些時候,特別是在進行核心程式設計時,在編譯時就能夠進行條件檢查的斷言,而不是在執行時進行,這非常有用。不幸的是,c99標準還不支援任何編譯時的斷言。

但是,我們可以利用預處理來生成**,這些**只有在某些條件成立時才會通過編譯(最好是那種不做實際功能的命令)。有各種各樣不同的方式都可以做到這一點,通常都是建立乙個大小為負的陣列或結構體。最常用的方式如下:

/* force a compilation error

if condition is

false

, but also produce a result

*(of value 0 and type size_t)

, so it can be used e.g.

in a structure

* initializer (

or wherever else comma expressions aren't permitted).*

//* linux calls these build_bug_on_zero/_null, which is rather misleading.*/

#define static_zero_assert(condition)

(sizeof(struct ))

#define static_null_assert(condition)

((void *

)static_zero_assert(condition))/

* force a compilation error

if condition is

false*/

#define static_assert(condition)

((void)static_zero_assert(condition))

如果(condition)計算結果為乙個非零值(即c中的真值),即! (condition)為零值,那麼**將能順利地編譯,並生成乙個大小為零的結構體。如果(condition)結果為0(在c真為假),那麼在試圖生成乙個負大小的結構體時,就會產生編譯錯誤。它的使用非常簡單,如果任何某假設條件能夠靜態地檢查,那麼它就可以在編譯時斷言。例如,在上面提到的標誌列表中,標誌集合的型別為uint32_t,所以,我們可以做以下斷言:

static_assert(total <

= 32)

它擴充套件為:

(void)sizeof(struct)

現在,假設total<=32。那麼-!(total <= 32)等於0,所以這行**相當於:

(void)sizeof(struct)

這是乙個合法的c**。現在假設標誌不止32個,那麼-!(total <= 32)等於-1,所以這時**就相當於:

(void)sizeof(struct)

因為位寬為負,所以可以確定,如果標誌的數量超過了我們指派的空間,那麼編譯將會失敗。

c語言技巧

1 關於一年天數的巨集定義 閏年366天 define isleapyear yr yr 400 yr 100 yr 4 define yearlength yr isleapyear yr 366 365 2 將秒換算成時間函式 typedef struct utctimestruct uint8...

C語言程式設計技巧

指定的初始化 intfibs c99標準實際上支援一種更為直觀簡單的方式來初始化各種不同的集合類資料 如 結構體,聯合體和陣列 陣列 我們可以指定陣列的元素來進行初始化。這非常有用,特別是當我們需要根據一組 define來保持某種對映關係的同步更新時。來看看一組錯誤碼的定義,如 entries ma...

c語言程式設計技巧

c語言常常讓人覺得它所能表達的東西非常有限。它不具有類似第一級函式和模式匹配這樣的高階功能。但是c非常簡單,並且仍然有一些非常有用的語法技巧和功能,只是沒有多少人知道罷了。指定的初始化 很多人都知道像這樣來靜態地初始化陣列 c int fibs c99標準實際上支援一種更為直觀簡單的方式來初始化各種...