OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2154|回复: 14

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

[复制链接]

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
发表于 2018-11-12 13:48:25 | 显示全部楼层 |阅读模式
最近写一些东西,其中一些用到可变参数宏会非常方便
并且学习到了获得可变参数宏参数数量的方法,如下
[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都正确)


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2018-11-12 13:50:53 | 显示全部楼层
本帖最后由 sppz 于 2018-11-12 13:52 编辑

扩展一下,我们能得到参数,那么我们也能通过参数的数量得到不同的行为,请看如下代码
[mw_shl_code=c,true]
#define __pm_arguments_join_1(action, head, tail, \
    argument0) (head##argument0##tail)
#define __pm_arguments_join_2(action, head, tail, \
    argument0, argument1) ((head##argument0##tail) action (head##argument1##tail))
#define __pm_arguments_join_3(action, head, tail, \
    argument0, argument1, argument2) ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail))
#define __pm_arguments_join_4(action, head, tail, \
    argument0, argument1, argument2, argument3) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail))
#define __pm_arguments_join_5(action, head, tail, \
    argument0, argument1, argument2, argument3, \
    argument4) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail) \
    action (head##argument4##tail))
#define __pm_arguments_join_6(action, head, tail, \
    argument0, argument1, argument2, argument3, argument4, argument5) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail) \
    action (head##argument4##tail) action (head##argument5##tail))
#define __pm_arguments_join_7(action, head, tail, \
    argument0, argument1, argument2, argument3, argument4, argument5, argument6) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail) \
    action (head##argument4##tail) action (head##argument5##tail) action (head##argument6##tail))
#define __pm_arguments_join_8(action, head, tail, \
    argument0, argument1, argument2, argument3, argument4, argument5, argument6, argument7) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail) \
    action (head##argument4##tail) action (head##argument5##tail) action (head##argument6##tail) action (head##argument7##tail))
#define __pm_arguments_join_9(action, head, tail, \
    argument0, argument1, argument2, argument3, argument4, argument5, argument6, argument7, \
    argument8) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail) \
    action (head##argument4##tail) action (head##argument5##tail) action (head##argument6##tail) action (head##argument7##tail) \
    action (head##argument8##tail))
/*
...
...
由于字数限制,这里省去了一大段
*/
#define __pm_arguments_join_30(action, head, tail, \
    argument0, argument1, argument2, argument3, argument4, argument5, argument6, argument7, \
    argument8, argument9, argument10, argument11, argument12, argument13, argument14, argument15, \
    argument16, argument17, argument18, argument19, argument20, argument21, argument22, argument23, \
    argument24, argument25, argument26, argument27, argument28, argument29) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail) \
    action (head##argument4##tail) action (head##argument5##tail) action (head##argument6##tail) action (head##argument7##tail) \
    action (head##argument8##tail) action (head##argument9##tail) action (head##argument10##tail) action (head##argument11##tail) \
    action (head##argument12##tail) action (head##argument13##tail) action (head##argument14##tail) action (head##argument15##tail) \
    action (head##argument16##tail) action (head##argument17##tail) action (head##argument18##tail) action (head##argument19##tail) \
    action (head##argument20##tail) action (head##argument21##tail) action (head##argument22##tail) action (head##argument23##tail) \
    action (head##argument24##tail) action (head##argument25##tail) action (head##argument26##tail) action (head##argument27##tail) \
    action (head##argument28##tail) action (head##argument29##tail))
#define __pm_arguments_join_31(action, head, tail, \
    argument0, argument1, argument2, argument3, argument4, argument5, argument6, argument7, \
    argument8, argument9, argument10, argument11, argument12, argument13, argument14, argument15, \
    argument16, argument17, argument18, argument19, argument20, argument21, argument22, argument23, \
    argument24, argument25, argument26, argument27, argument28, argument29, argument30) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail) \
    action (head##argument4##tail) action (head##argument5##tail) action (head##argument6##tail) action (head##argument7##tail) \
    action (head##argument8##tail) action (head##argument9##tail) action (head##argument10##tail) action (head##argument11##tail) \
    action (head##argument12##tail) action (head##argument13##tail) action (head##argument14##tail) action (head##argument15##tail) \
    action (head##argument16##tail) action (head##argument17##tail) action (head##argument18##tail) action (head##argument19##tail) \
    action (head##argument20##tail) action (head##argument21##tail) action (head##argument22##tail) action (head##argument23##tail) \
    action (head##argument24##tail) action (head##argument25##tail) action (head##argument26##tail) action (head##argument27##tail) \
    action (head##argument28##tail) action (head##argument29##tail) action (head##argument30##tail))
#define __pm_arguments_join_32(action, head, tail, \
    argument0, argument1, argument2, argument3, argument4, argument5, argument6, argument7, \
    argument8, argument9, argument10, argument11, argument12, argument13, argument14, argument15, \
    argument16, argument17, argument18, argument19, argument20, argument21, argument22, argument23, \
    argument24, argument25, argument26, argument27, argument28, argument29, argument30, argument31) \
    ((head##argument0##tail) action (head##argument1##tail) action (head##argument2##tail) action (head##argument3##tail) \
    action (head##argument4##tail) action (head##argument5##tail) action (head##argument6##tail) action (head##argument7##tail) \
    action (head##argument8##tail) action (head##argument9##tail) action (head##argument10##tail) action (head##argument11##tail) \
    action (head##argument12##tail) action (head##argument13##tail) action (head##argument14##tail) action (head##argument15##tail) \
    action (head##argument16##tail) action (head##argument17##tail) action (head##argument18##tail) action (head##argument19##tail) \
    action (head##argument20##tail) action (head##argument21##tail) action (head##argument22##tail) action (head##argument23##tail) \
    action (head##argument24##tail) action (head##argument25##tail) action (head##argument26##tail) action (head##argument27##tail) \
    action (head##argument28##tail) action (head##argument29##tail) action (head##argument30##tail) action (head##argument31##tail))
#define __pm_arguments_join(action, head, tail, ...) __pm_arguments_expand(__pm_arguments_map(action, __VA_ARGS__, \
    __pm_arguments_join_32, __pm_arguments_join_31, __pm_arguments_join_30, __pm_arguments_join_29, \
    __pm_arguments_join_28, __pm_arguments_join_27, __pm_arguments_join_26, __pm_arguments_join_25, \
    __pm_arguments_join_24, __pm_arguments_join_23, __pm_arguments_join_22, __pm_arguments_join_21, \
    __pm_arguments_join_20, __pm_arguments_join_19, __pm_arguments_join_18, __pm_arguments_join_17, \
    __pm_arguments_join_16, __pm_arguments_join_15, __pm_arguments_join_14, __pm_arguments_join_13, \
    __pm_arguments_join_12, __pm_arguments_join_11, __pm_arguments_join_10, __pm_arguments_join_9, \
    __pm_arguments_join_8, __pm_arguments_join_7, __pm_arguments_join_6, __pm_arguments_join_5, \
    __pm_arguments_join_4, __pm_arguments_join_3, __pm_arguments_join_2, __pm_arguments_join_1)(action, head, tail, __VA_ARGS__))
[/mw_shl_code]
以上一大段实现了用action拼接所有参数的作用(顺便在参数上加上前缀和后缀)
[mw_shl_code=c,true]
__pm_arguments_join(|, , , 1, 2, 3, 4); //相当于(1) | (2) | (3) | (4)
[/mw_shl_code]
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2018-11-12 13:51:19 | 显示全部楼层
本帖最后由 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
回复 支持 反对

使用道具 举报

4

主题

346

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3657
金钱
3657
注册时间
2016-2-21
在线时间
542 小时
发表于 2018-11-12 14:04:04 | 显示全部楼层
Mark一下
回复 支持 反对

使用道具 举报

79

主题

399

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1829
金钱
1829
注册时间
2015-9-21
在线时间
561 小时
发表于 2018-11-12 14:41:31 | 显示全部楼层
看着好乱!!
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2018-11-12 15:06:46 | 显示全部楼层

这么整齐你居然说乱...
回复 支持 反对

使用道具 举报

22

主题

2251

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4480
金钱
4480
注册时间
2013-4-22
在线时间
337 小时
发表于 2018-11-12 15:25:45 | 显示全部楼层
C语言参数本来就可以声明可变参数
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2018-11-12 15:41:49 | 显示全部楼层
三叶草 发表于 2018-11-12 15:25
C语言参数本来就可以声明可变参数

你好好看,理解一下...
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-11-12 16:28:34 | 显示全部楼层
什么东西
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2018-11-12 16:30:50 | 显示全部楼层

实际上是用来写c/c++(库)的技巧
能写出可读性非常强的代码的技巧
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-11-12 16:32:15 | 显示全部楼层
sppz 发表于 2018-11-12 16:30
实际上是用来写c/c++(库)的技巧
能写出可读性非常强的代码的技巧

骚操作
Loto虚拟示波器 官方qq群: 706769836 https://shop296209296.taobao.com/shop/view_shop.htm?tracelog=t
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2018-11-12 16:33:29 | 显示全部楼层

对的
奇技淫巧
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-11-12 16:35:47 | 显示全部楼层

不够霸气   奇淫技巧  是不是更好
Loto虚拟示波器 官方qq群: 706769836 https://shop296209296.taobao.com/shop/view_shop.htm?tracelog=t
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2018-11-12 16:36:42 | 显示全部楼层
秋天 发表于 2018-11-12 16:35
不够霸气   奇淫技巧  是不是更好

你淫了
回复 支持 反对

使用道具 举报

15

主题

184

帖子

0

精华

高级会员

Rank: 4

积分
647
金钱
647
注册时间
2014-4-29
在线时间
299 小时
发表于 2018-11-12 22:09:12 | 显示全部楼层
卧槽,这个吊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-22 05:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表