搜索
bottom↓
回复: 17

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

[复制链接]

出0入4汤圆

发表于 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       
不知道问题出在哪里?



阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

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

出0入4汤圆

 楼主| 发表于 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),所以就报错了

修改错别字

出0入442汤圆

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

出0入4汤圆

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

就是为了能生成一个巨大的数组,里面的数据由宏自动生成

出0入8汤圆

发表于 2019-1-18 15:16:09 来自手机 | 显示全部楼层
你需要boost_pp
不光能自增,还能配合boost array进行枚举
不过不建议这么搞,可读性太差,还不如弄个脚本自动生成一下

出0入0汤圆

发表于 2019-1-18 16:00:06 | 显示全部楼层
liuqian 发表于 2019-1-18 14:45
就是为了能生成一个巨大的数组,里面的数据由宏自动生成

你的想法很有道理,这在生成有规律的数据时候很有用,我觉得你可以试试用脚本生成,也可以用tcc把c文件作为脚本

出0入362汤圆

发表于 2019-1-18 21:02:00 | 显示全部楼层
用类似iap的方式, 上电后写到flash里好了,一共也要不了几行代码。

出0入8汤圆

发表于 2019-1-18 22:56:29 来自手机 | 显示全部楼层
tomzbj 发表于 2019-1-18 21:02
用类似iap的方式, 上电后写到flash里好了,一共也要不了几行代码。

这个方法也不不错

出0入4汤圆

发表于 2019-1-18 23:01:44 | 显示全部楼层
在pc机上用脚本生成你需要的数组代码,然后把代码拷贝到程序文件里,再编译。。。笨办法;
在pc上写个 c程序或者shell脚本,printf出来 const char xxx[]={xxx,xxx,xxx,xxx};

出0入20汤圆

发表于 2019-1-19 00:48:28 | 显示全部楼层
直接excel写好公式然后一拉到底,然后另存为CVS文件,然后记事本打开另存为ASCII编码文件,连分隔符都做好成逗号了~

出0入93汤圆

发表于 2019-1-19 07:22:52 | 显示全部楼层
11楼的方法是最方便的,再进一步改进如下:
第一步:直接excel写好公式然后一拉到底(优先选向右拉),然后另存为CVS文件,比如abc.cvs。
第二步:在你的C文件中写入
  1. const uint32_t DATA[]={
  2.     #include "abc.cvs"
  3. };
复制代码
这个只要一开始写一次就行了,以后都不用改动。

出0入0汤圆

发表于 2019-1-19 07:43:18 | 显示全部楼层
#include "abc.cvs"  这样用很方便

出0入296汤圆

发表于 2019-1-19 08:05:49 来自手机 | 显示全部楼层
你们都没听说__COUNT__宏吧……

出0入0汤圆

发表于 2019-1-19 15:43:52 | 显示全部楼层
Gorgon_Meducer 发表于 2019-1-19 08:05
你们都没听说__COUNT__宏吧……

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

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

和编译器有关,在IAR for ARM V7.4 认,其他两个编译器不认。

出0入0汤圆

发表于 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};

出0入296汤圆

发表于 2019-1-21 19:28:29 | 显示全部楼层
zhanan 发表于 2019-1-19 15:43
谢谢,头次听说,立刻试了试。

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

Arm Compiler 和 IAR都支持,GCC自然不必说。

出0入0汤圆

发表于 2020-1-15 14:49:30 | 显示全部楼层
MARK   C语言宏定义。。。。。。。。。。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 17:52

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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