最新电影在线观看,jrs低调看直播,avav天堂,囯产精品宾馆在线精品酒店,亚洲精品成人区在线观看

分享幾個優雅的C/C++宏

1引言

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

NAME2/UNIQUE_NAME

NAME2宏的實現如下,功能是將兩個字符連接成一個字符。對于UNIQUE_NAME宏,則是在NAME2的基礎上增加一個__LINE__參數,從而生成一個根據當前調用處的行數生成一個以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為計算靜態數組的長度。IS_ARRAY則是判斷參數的類型是否為數組,而非指針。定義如下:

#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為遍歷數組的每個元素,第三個參數為閉包,可以被宏內部調用。

#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為定義一系列相同的清單項,如子項名與序號等,實現如下。

#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統一定義了所有的子項名字和對應的值,ITEM_DEF在不同的場合定義不同的實現,可以看到,ITEM_DEF在枚舉item_n中添加各個名字和對應的序號,在結構體item_t中添加所有的名字。然后在全局靜態變量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結語

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

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