[奇技淫巧]c可变参数宏的某技巧

2019-07-21 08:01发布

最近写一些东西,其中一些用到可变参数宏会非常方便
并且学习到了获得可变参数宏参数数量的方法,如下
[mw_shl_code=c,true]
#define __pm_arguments_expand(...) __VA_ARGS__
#define __pm_arguments_map(
    _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17,
    _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, n, ...) n
#define __pm_arguments_count(...) __pm_arguments_expand(__pm_arguments_map(0, __VA_ARGS__,
    32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
    16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))

[/mw_shl_code]

原理是通过参数位置差获得n位置的值,其值就是参数数量(我们传过去的)的值(vs下0个参数值为1,clang下0-32都正确)


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
14条回答
sppz
1楼-- · 2019-07-21 12:43
 精彩回答 2  元偷偷看……
sppz
2楼-- · 2019-07-21 17:05
本帖最后由 sppz 于 2018-11-12 13:54 编辑

有了这个我们就能写出可读性非常高的代码,并且只要定义mask和value就能非常清晰简单的操作寄存器了,看下面
[mw_shl_code=c,true]
typedef volatile pm_unsigned_integer_16_type pm_register_16_value_type;
typedef volatile pm_unsigned_integer_32_type pm_register_32_value_type;
typedef volatile pm_unsigned_integer_16_type *pm_register_16_type;
typedef volatile pm_unsigned_integer_32_type *pm_register_32_type;
#define __pm_register_16_maker(base, offset) ((pm_register_16_type)((base) + (offset)))
#define __pm_register_32_maker(base, offset) ((pm_register_32_type)((base) + (offset)))
#define pm_register_get(register, ...) (*(register) & __pm_arguments_join(|, , _mask, __VA_ARGS__))
#define pm_register_set(register, ...)
    (*(register) = ((*(register)) & (~__pm_arguments_join(|, , _mask, __VA_ARGS__))) | __pm_arguments_join(|, , _value, __VA_ARGS__))

#define pm_register_FLASH_access_control __pm_register_32_maker(0x11, 0x0)
#define V1() //这是一个技巧,让编辑器能出现提示,又不会由于展开出现错误
#define V1_value 1
#define V1_mask 0x1 << 0
#define V2()
#define V2_value 2
#define V2_mask 0x1 << 1
#define V4()
#define V4_value 4
#define V4_mask 0x1 << 2
//#include <stdio.h>
void test() {
        __pm_arguments_count();
        pm_register_set(pm_register_FLASH_access_control, V1, V2, V4); // 这里相当于 *pm_register_FLASH_access_control = ((*pm_register_FLASH_access_control) & (~(7))) | 7;
}
[/mw_shl_code]
可以看到非常的清晰,代码中不会出现任何有疑问的值,且值定义起来也非常容易
以上在clang和vs上测试,且版本都是很新的,over
shikihane
3楼-- · 2019-07-21 17:48
Mark一下
硕果累累
4楼-- · 2019-07-21 18:10
看着好乱!!
sppz
5楼-- · 2019-07-21 23:21
硕果累累 发表于 2018-11-12 14:41
看着好乱!!

这么整齐你居然说乱...
三叶草
6楼-- · 2019-07-22 03:18
 精彩回答 2  元偷偷看……

一周热门 更多>