超級炫酷的C語言技巧!
來源:百問科技
int fibs[] = {1, 1, 2, 3, 5};C99標(biāo)準(zhǔn)實(shí)際上支持一種更為直觀簡單的方式來初始化各種不同的集合類數(shù)據(jù)(如:結(jié)構(gòu)體,聯(lián)合體和數(shù)組)。
/* 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] = "Success",[EINVAL] = "Invalid argument",[ENOMEM] = "Not enough memory",[EFAULT] = "Bad address",/* ... */[E2BIG ] = "Argument list too long",[EBUSY ] = "Device or resource busy",/* ... */[ECHILD] = "No child processes"/* ... */};
struct point {int x;int y;int z;}
然后我們這樣初始化struct point:
struct point p = {.x = 3, .y = 4, .z = 5};當(dāng)我們不想將所有字段都初始化為0時,這種作法可以很容易的在編譯時就生成結(jié)構(gòu)體,而不需要專門調(diào)用一個初始化函數(shù)。
對聯(lián)合體來說,我們可以使用相同的辦法,只是我們只用初始化一個字段。
#define FLAG_LIST(_) \_(InWorklist) \_(EmittedAtUses) \_(LoopInvariant) \_(Commutative) \_(Movable) \_(Lowered) \_(Guard)
#define DEFINE_FLAG(flag) flag,enum Flag {None = 0,FLAG_LIST(DEFINE_FLAG)Total};#undef DEFINE_FLAG
enum Flag {None = 0,DEFINE_FLAG(InWorklist)DEFINE_FLAG(EmittedAtUses)DEFINE_FLAG(LoopInvariant)DEFINE_FLAG(Commutative)DEFINE_FLAG(Movable)DEFINE_FLAG(Lowered)DEFINE_FLAG(Guard)Total};
enum Flag {None = 0,InWorklist,EmittedAtUses,LoopInvariant,Commutative,Movable,Lowered,Guard,Total};
#define FLAG_ACCESSOR(flag) \bool is##flag() const {\return hasFlags(1 << flag);\}\void set##flag() {\JS_ASSERT(!hasFlags(1 << flag));\setFlags(1 << flag);\}\void setNot##flag() {\JS_ASSERT(hasFlags(1 << flag));\removeFlags(1 << flag);\}FLAG_LIST(FLAG_ACCESSOR)#undef FLAG_ACCESSOR
一步步的展示其過程是非常有啟發(fā)性的,如果對它的使用還有不解,可以花一些時間在gcc –E上。
但是,我們可以利用預(yù)處理來生成代碼,這些代碼只有在某些條件成立時才會通過編譯(最好是那種不做實(shí)際功能的命令)。有各種各樣不同的方式都可以做到這一點(diǎn),通常都是建立一個大小為負(fù)的數(shù)組或結(jié)構(gòu)體。最常用的方式如下:
/* 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 { int:-!(condition); }) )#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))
它的使用非常簡單,如果任何某假設(shè)條件能夠靜態(tài)地檢查,那么它就可以在編譯時斷言。例如,在上面提到的標(biāo)志列表中,標(biāo)志集合的類型為uint32_t,所以,我們可以做以下斷言:
STATIC_ASSERT(Total <= 32)(void)sizeof(struct { int:-!(Total <= 32) })(void)sizeof(struct { int: 0 })(void)sizeof(struct { int: -1 } )評論
圖片
表情
