amoBBS 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
查看: 914|回复: 16

请教大家一个C语言的宏的递归完成自增定义的方法

[复制链接]
发表于 2019-1-18 13:27:27 | 显示全部楼层 |阅读模式
思路这这样的:
为了测试,需要一个数据块,数据的形式是0x55aa0000,0x55aa0001,0x55aa0002,0x55aa0003 。。。,共n*4个字节,如果放在ram中太浪费,就想直接生成到flash
笨办法就是直接写死,比如
const uint32_t DATA[60]={0x55aa0000,0x55aa0001,0x55aa0002,0x55aa0003 。。。,0x55aa003F};

但是为了能方便调整大小,就考虑用宏递归,而且最好前面的0x55aa也能用宏定义

在asf中有如下的宏
/*! \brief Macro repeat.
*
* This macro represents a horizontal repetition construct.
*
* \param count  The number of repetitious calls to macro. Valid values range from 0 to MREPEAT_LIMIT.
* \param macro  A binary operation of the form macro(n, data). This macro is expanded by MREPEAT with
*               the current repetition number and the auxiliary data argument.
* \param data   Auxiliary data passed to macro.
*
* \return       <tt>macro(0, data) macro(1, data) ... macro(count - 1, data)</tt>
*/

#define TPASTE2( a, b)                            a##b

#define MREPEAT(count, macro, data)         TPASTE2(MREPEAT, count)(macro, data)

#define MREPEAT0(  macro, data)
#define MREPEAT1(  macro, data)       MREPEAT0(  macro, data)   macro(  0, data)
#define MREPEAT2(  macro, data)       MREPEAT1(  macro, data)   macro(  1, data)
#define MREPEAT3(  macro, data)       MREPEAT2(  macro, data)   macro(  2, data)
#define MREPEAT4(  macro, data)       MREPEAT3(  macro, data)   macro(  3, data)
#define MREPEAT5(  macro, data)       MREPEAT4(  macro, data)   macro(  4, data)
#define MREPEAT6(  macro, data)       MREPEAT5(  macro, data)   macro(  5, data)
#define MREPEAT7(  macro, data)       MREPEAT6(  macro, data)   macro(  6, data)
。。。。
#define MREPEAT256(macro, data)       MREPEAT255(macro, data)   macro(255, data)

然后我用这个宏来生成自增定义

#define KEY_HEADER 0x55aa0000
#define X 16
#define Y 4
#define KEY_SIZE X*Y
#define KEY_HEADER_PLUS(c,d) c+d,
const uint32_t DATA[KEY_SIZE]={ // 160 bytes = 40 words
        MREPEAT(KEY_SIZE, KEY_HEADER_PLUS, KEY_HEADER)
};

期望得到的结果是:
const uint32_t DATA[KEY_SIZE]={ // 160 bytes = 40 words
0x55aa0000,0x55aa0001,0x55aa0002,0x55aa0003 。。。,0x55aa003F,
};

但是上面的那段程序总是报错,无法通过编译
pasting "MREPEAT" and "(" does not give a valid preprocessing token       
不知道问题出在哪里?



发表于 2019-1-18 13:41:03 | 显示全部楼层
正巧前几天看到这个帖子,可能会对你有帮助
https://www.amobbs.com/thread-5511786-1-1.html
 楼主| 发表于 2019-1-18 13:56:18 | 显示全部楼层
liansh2002 发表于 2019-1-18 13:41
正巧前几天看到这个帖子,可能会对你有帮助
https://www.amobbs.com/thread-5511786-1-1.html ...


谢谢,帖子里面傻孩子提到:宏MREPEAT实际上只能接受实际的数值,也就是说,这里的REQ_ITEM_COUNT_BYTE必须是一个常数,而不能是任何表达式
我把
#define KEY_SIZE X*Y
替换成
#define KEY_SIZE 64

编译通过

我的解释,不知道对不对:
当KEY_SIZE被定义为64
MREPEAT(KEY_SIZE, KEY_HEADER_PLUS, KEY_HEADER)
展开一步
MREPEAT40(KEY_HEADER_PLUS, KEY_HEADER),然后再递归展开

如果KEY_SIZE定义为 X*Y
展开一步
MREPEATX*Y(KEY_HEADER_PLUS, KEY_HEADER),所以就报错了

修改错别字
发表于 2019-1-18 14:37:43 来自手机 | 显示全部楼层
你为吗不直接写个巨大的数组,反正const我记得都在rodata里面。
 楼主| 发表于 2019-1-18 14:45:59 | 显示全部楼层
wye11083 发表于 2019-1-18 14:37
你为吗不直接写个巨大的数组,反正const我记得都在rodata里面。

就是为了能生成一个巨大的数组,里面的数据由宏自动生成
发表于 2019-1-18 15:16:09 来自手机 | 显示全部楼层
你需要boost_pp
不光能自增,还能配合boost array进行枚举
不过不建议这么搞,可读性太差,还不如弄个脚本自动生成一下
发表于 2019-1-18 16:00:06 | 显示全部楼层
liuqian 发表于 2019-1-18 14:45
就是为了能生成一个巨大的数组,里面的数据由宏自动生成

你的想法很有道理,这在生成有规律的数据时候很有用,我觉得你可以试试用脚本生成,也可以用tcc把c文件作为脚本
发表于 2019-1-18 21:02:00 | 显示全部楼层
用类似iap的方式, 上电后写到flash里好了,一共也要不了几行代码。
发表于 2019-1-18 22:56:29 来自手机 | 显示全部楼层
tomzbj 发表于 2019-1-18 21:02
用类似iap的方式, 上电后写到flash里好了,一共也要不了几行代码。

这个方法也不不错
发表于 2019-1-18 23:01:44 | 显示全部楼层
在pc机上用脚本生成你需要的数组代码,然后把代码拷贝到程序文件里,再编译。。。笨办法;
在pc上写个 c程序或者shell脚本,printf出来 const char xxx[]={xxx,xxx,xxx,xxx};
发表于 2019-1-19 00:48:28 | 显示全部楼层
直接excel写好公式然后一拉到底,然后另存为CVS文件,然后记事本打开另存为ASCII编码文件,连分隔符都做好成逗号了~
发表于 2019-1-19 07:22:52 | 显示全部楼层
11楼的方法是最方便的,再进一步改进如下:
第一步:直接excel写好公式然后一拉到底(优先选向右拉),然后另存为CVS文件,比如abc.cvs。
第二步:在你的C文件中写入
  1. const uint32_t DATA[]={
  2.     #include "abc.cvs"
  3. };
复制代码
这个只要一开始写一次就行了,以后都不用改动。
发表于 2019-1-19 07:43:18 | 显示全部楼层
#include "abc.cvs"  这样用很方便
发表于 2019-1-19 08:05:49 来自手机 | 显示全部楼层
你们都没听说__COUNT__宏吧……
发表于 2019-1-19 15:43:52 | 显示全部楼层
Gorgon_Meducer 发表于 2019-1-19 08:05
你们都没听说__COUNT__宏吧……

谢谢,头次听说,立刻试了试。

__COUNT__  宏代换的结果是一个从0开始的整数,每次自动+1。

和编译器有关,在IAR for ARM V7.4 认,其他两个编译器不认。
发表于 2019-1-19 17:26:54 | 显示全部楼层
本帖最后由 zhanan 于 2019-1-19 18:34 编辑

#define xxx __COUNTER__
#define MREPEAT0  xxx
#define MREPEAT1  xxx,MREPEAT0
#define MREPEAT2  xxx,MREPEAT1
#define MREPEAT3  xxx,MREPEAT2

u8 mmxx[4]={MREPEAT3};  =========== u8 mmxx[4]={0,1,2,3};

或者
#define xxx __COUNTER__
#define MREPEAT0  xxx,MREPEAT1
#define MREPEAT1  xxx,MREPEAT2
#define MREPEAT2  xxx,MREPEAT3
#define MREPEAT3  xxx

u8 mmxx[4]={MREPEAT0};  =========== u8 mmxx[4]={0,1,2,3};
发表于 2019-1-21 19:28:29 | 显示全部楼层
zhanan 发表于 2019-1-19 15:43
谢谢,头次听说,立刻试了试。

__COUNT__  宏代换的结果是一个从0开始的整数,每次自动+1。

Arm Compiler 和 IAR都支持,GCC自然不必说。
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|阿莫电子论坛(原ourAVR/ourDEV) ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号 )

GMT+8, 2019-7-20 12:14

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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