liuqian 发表于 2019-1-18 13:27:27

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

思路这这样的:
为了测试,需要一个数据块,数据的形式是0x55aa0000,0x55aa0001,0x55aa0002,0x55aa0003 。。。,共n*4个字节,如果放在ram中太浪费,就想直接生成到flash
笨办法就是直接写死,比如
const uint32_t DATA={0x55aa0000,0x55aa0001,0x55aa0002,0x55aa0003 。。。,0x55aa003F};

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

在asf中有如下的宏
/*! \brief Macro repeat.
*
* This macro represents a horizontal repetition construct.
*
* \param countThe number of repetitious calls to macro. Valid values range from 0 to MREPEAT_LIMIT.
* \param macroA 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={ // 160 bytes = 40 words
        MREPEAT(KEY_SIZE, KEY_HEADER_PLUS, KEY_HEADER)
};

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

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



liansh2002 发表于 2019-1-18 13:41:03

正巧前几天看到这个帖子,可能会对你有帮助
https://www.amobbs.com/thread-5511786-1-1.html

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

修改错别字

wye11083 发表于 2019-1-18 14:37:43

你为吗不直接写个巨大的数组,反正const我记得都在rodata里面。

liuqian 发表于 2019-1-18 14:45:59

wye11083 发表于 2019-1-18 14:37
你为吗不直接写个巨大的数组,反正const我记得都在rodata里面。

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

canspider 发表于 2019-1-18 15:16:09

你需要boost_pp
不光能自增,还能配合boost array进行枚举
不过不建议这么搞,可读性太差,还不如弄个脚本自动生成一下

myxiaonia 发表于 2019-1-18 16:00:06

liuqian 发表于 2019-1-18 14:45
就是为了能生成一个巨大的数组,里面的数据由宏自动生成

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

tomzbj 发表于 2019-1-18 21:02:00

用类似iap的方式, 上电后写到flash里好了,一共也要不了几行代码。

了无 发表于 2019-1-18 22:56:29

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

这个方法也不不错

snkaka 发表于 2019-1-18 23:01:44

在pc机上用脚本生成你需要的数组代码,然后把代码拷贝到程序文件里,再编译。。。笨办法;
在pc上写个 c程序或者shell脚本,printf出来 const char xxx[]={xxx,xxx,xxx,xxx};

Error.Dan 发表于 2019-1-19 00:48:28

直接excel写好公式然后一拉到底,然后另存为CVS文件,然后记事本打开另存为ASCII编码文件,连分隔符都做好成逗号了~

takashiki 发表于 2019-1-19 07:22:52

11楼的方法是最方便的,再进一步改进如下:
第一步:直接excel写好公式然后一拉到底(优先选向右拉),然后另存为CVS文件,比如abc.cvs。
第二步:在你的C文件中写入const uint32_t DATA[]={
    #include "abc.cvs"
};这个只要一开始写一次就行了,以后都不用改动。

cl1cl1cl1cl1 发表于 2019-1-19 07:43:18

#include "abc.cvs"这样用很方便

Gorgon_Meducer 发表于 2019-1-19 08:05:49

你们都没听说__COUNT__宏吧……

zhanan 发表于 2019-1-19 15:43:52

Gorgon_Meducer 发表于 2019-1-19 08:05
你们都没听说__COUNT__宏吧……

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

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

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

zhanan 发表于 2019-1-19 17:26:54

本帖最后由 zhanan 于 2019-1-19 18:34 编辑

#define xxx __COUNTER__
#define MREPEAT0xxx
#define MREPEAT1xxx,MREPEAT0
#define MREPEAT2xxx,MREPEAT1
#define MREPEAT3xxx,MREPEAT2

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

或者
#define xxx __COUNTER__
#define MREPEAT0xxx,MREPEAT1
#define MREPEAT1xxx,MREPEAT2
#define MREPEAT2xxx,MREPEAT3
#define MREPEAT3xxx

u8 mmxx={MREPEAT0};=========== u8 mmxx={0,1,2,3};

Gorgon_Meducer 发表于 2019-1-21 19:28:29

zhanan 发表于 2019-1-19 15:43
谢谢,头次听说,立刻试了试。

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


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

diego2003 发表于 2020-1-15 14:49:30

MARK   C语言宏定义。。。。。。。。。。。
页: [1]
查看完整版本: 请教大家一个C语言的宏的递归完成自增定义的方法