日韩在线不卡免费视频一区,日韩欧美精品一区二区三区经典,日产精品码2码三码四码区,人妻无码一区二区三区免费,日本feerbbwdh少妇丰满

Rust嵌入式
認(rèn)證:普通會員
作者動態(tài)
Rust國產(chǎn)單片機(jī)燒錄小工具
21小時前
放棄printf,使用println優(yōu)雅打印
2天前
5分鐘入門Rust基礎(chǔ)
4天前
分享幾個優(yōu)雅的C/C++宏
1星期前
Esp32 Rust環(huán)境搭建
1星期前

分享幾個優(yōu)雅的C/C++宏

1引言

C或C++開發(fā)中,我們經(jīng)常會在代碼中使用一些宏來簡化編碼,提升可閱讀性。這里我總結(jié)了一些常用的、有趣的宏。

NAME2/UNIQUE_NAME

NAME2宏的實(shí)現(xiàn)如下,功能是將兩個字符連接成一個字符。對于UNIQUE_NAME宏,則是在NAME2的基礎(chǔ)上增加一個__LINE__參數(shù),從而生成一個根據(jù)當(dāng)前調(diào)用處的行數(shù)生成一個以prefix為前綴的字符。

#define __NAME2_HELPER(a, b)      a ## b
#define NAME2(a, b)               __NAME2_HELPER(a, b)

#define UNIQUE_NAME(prefix)       NAME2(NAME2(prefix, _), __LINE__)

測試如下:

// int a1 = 5;
int NAME2(a, 1) = 5;
// NAME2(a, 1): 5 = 5
printf("NAME2(a, 1): %d = %d\n", a1, NAME2(a, 1));
// STR(NAME2(a, 1)): a1
printf("STR(NAME2(a, 1)): %s\n", STR(NAME2(a, 1)));
// STR(STR(NAME2(a, 1))): "a1"
printf("STR(STR(NAME2(a, 1))): %s\n", STR(STR(NAME2(a, 1))));
STR(ABCD): ABCD
printf("STR(ABCD): %s\n", STR(ABCD));
// int val_11 = 0;
int UNIQUE_NAME(val) = 0;

ARRAY_SIZE

ARRAY_SIZE為計算靜態(tài)數(shù)組的長度。IS_ARRAY則是判斷參數(shù)的類型是否為數(shù)組,而非指針。定義如下:

#define ARRAY_SIZE(arr)           (sizeof(arr)/sizeof(0[arr]))

# define _IS_SAME_TYPE(T1,T2) \
    __builtin_types_compatible_p(__typeof__(T1), __typeof__(T2))
#define IS_ARRAY(A)  !_IS_SAME_TYPE( (A), &(A)[0] )

測試如下:

uint8_t arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
/* 輸出
 ARRAY_SIZE(arr): 10
        index: 0: 0
        index: 1: 1
        index: 2: 2
        index: 3: 3
        index: 4: 4
        index: 5: 5
        index: 6: 6
        index: 7: 7
        index: 8: 8
        index: 9: 9
*/
printf("ARRAY_SIZE(arr): %ld\n", ARRAY_SIZE(arr));
for (size_t i = 0; i < ARRAY_SIZE(arr); i++) {
    printf("    index: %ld: %d\n", i, arr[i]);
}

int arr1[10];
int *ptr1 = arr1;
// arr1[10]: 1
printf("arr1[10]: %d\n", IS_ARRAY(arr1));
// val1: 0
printf("val1: %d\n", IS_ARRAY(ptr1));

FOREACH_ARRAY_ELEMENT

FOREACH_ARRAY_ELEMENT為遍歷數(shù)組的每個元素,第三個參數(shù)為閉包,可以被宏內(nèi)部調(diào)用。

#define FOREACH_ARRAY_ELEMENT(arr, item_ptr, closure)   \
    do{                                                 \
        for (size_t i = 0; i < ARRAY_SIZE(arr); i++ ) { \
            typeof(arr[0]) *item_ptr = arr + i;         \
            {closure}                                   \
        }                                               \
    }while(0)

測試如下:

/*  輸出:
 A B C D E F G
*/
char char_list[7] = "abcdefg";
    FOREACH_ARRAY_ELEMENT(char_list, p_ch, {
        printf("%c ", *p_ch - 'a' + 'A');
    });

ITEM_DEF_LIST/ITEM_DEF

ITEM_DEF_LIST/ITEM_DEF為定義一系列相同的清單項(xiàng),如子項(xiàng)名與序號等,實(shí)現(xiàn)如下。

#define ITEM_DEF_LIST   \
            ITEM_DEF(a1, 1, 1) \
            ITEM_DEF(a2, 2, 3) \
            ITEM_DEF(a3, 3, 5) \
            ITEM_DEF(a4, 4, 7) \
            ITEM_DEF(a5, 5, 9)

typedef enum _item_n{
#define ITEM_DEF(name, idx, val)         NAME2(item, name) = idx,

    ITEM_DEF_LIST
#undef ITEM_DEF
}item_n;

typedef struct _item{
#define ITEM_DEF(name, idx, val)         int name;

    ITEM_DEF_LIST
#undef ITEM_DEF
}item_t;

static item_t s_item_init = {
#define ITEM_DEF(name, idx, val)         .name = val,

    ITEM_DEF_LIST
#undef ITEM_DEF

代碼中使用ITEM_DEF_LIST統(tǒng)一定義了所有的子項(xiàng)名字和對應(yīng)的值,ITEM_DEF在不同的場合定義不同的實(shí)現(xiàn),可以看到,ITEM_DEF在枚舉item_n中添加各個名字和對應(yīng)的序號,在結(jié)構(gòu)體item_t中添加所有的名字。然后在全局靜態(tài)變量s_item_init中添加初始化的值。測試如下:

#define ITEM_DEF(name, idx, val)  \
         printf("%s: enum: %d val: %d\n", \
            STR(s_item_init.name),          \
            (int)NAME2(item, name),         \
            s_item_init.name);
/*
 輸出:
    s_item_init.a1: enum: 1 val: 1
    s_item_init.a2: enum: 2 val: 3
    s_item_init.a3: enum: 3 val: 5
    s_item_init.a4: enum: 4 val: 7
    s_item_init.a5: enum: 5 val: 9
*/
ITEM_DEF_LIST
#undef ITEM_DEF

2結(jié)語

C語言還有非常多的高級宏的寫法,有空再分享一波!

聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關(guān)注 19
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧