【C】利用 _Generic 重载 参数数目不同的函数

< 看之前需要先了解一下_Generic 的基本用法         -- 周树人 >

形式:

这是两个 链表初始化函数:

Link_t  void_init (Link_t _head);                                        // initalize the head
Link_t  arr_init  (Link_t _head, int32_t* _arr, size_t _lenth);          // initalize with an arr

我们使用 _Generic关键字和可变参数  来模拟  模板和缺省参数:

#define init(...)                                   \
    _Generic(&(uintptr_t[]){(uintptr_t)__VA_ARGS__},\
        uintptr_t(*)[3] : arr_init,                 \
        default : void_init)(__VA_ARGS__) // 泛型初始化

 分析:

#define  init( ~ )  _Generic( ~ )
//宏替换 _Generic 为我们需要的 init 函数

由于我们两个函数的参数数量不同,所以我们使用 可变参数:

#define  init( ... ) _Generic( ~ )(__VA_ARGS__)
// ... 和 __VA_ARGS__ 就是可变参数的基本形式, __VA_ARGS__ 会引用  ... 接收到的参数
_Generic 里面:
&(uintptr_t[]){(uintptr_t)__VA_ARGS__}
/*这句话的基本形式是 {__VA_ARGS__},这是一个数组,用于存放接收到的参数
 *我们将它强制转换为 uintptr_t 类型(unsigned long long), 这个类型一般用于存取指针数据,因为它足够大, 所以一般不会丢失数据
 *为什么我们需要这样转换数据类型? 因为在这两个函数里面,参数类型也是不同的,数组无法存储不同类型的参数
*数组完成之后我们将它再转换为 uintptr_t[]这样一个数组,取这个数组的地址进行比较(数组本体太大了_Generic无法直接比较)
*/
uintptr_t(*)[3]  :  arr_init,                 
default          :  void_init

/* 对第一个参数进行选择:
 * 在上面我们取的是数组的地址,自然就要数组指针来匹配
 * 如果有3个参数,那么宏替换为arr_init函数
 * 默认替换为 void_init 函数
 */

 

posted @ 2022-08-29 15:43  HeHonbo  阅读(221)  评论(0)    收藏  举报