9189|44

9805

帖子

24

TA的资源

版主

楼主
 

c语言高手请进,关于宏定义问题 [复制链接]

 
本帖最后由 littleshrimp 于 2015-4-21 10:28 编辑

想使用宏创建一个指定长度的数组,例如

  1. #define CREATE_ARRAY(x)  uint8_t buf[x] = {1,\
  2.                          2,\
  3.                          3,\
  4.                          4};
复制代码


执行下边代码

  1. CREATE_ARRAY(4);
复制代码
会生成下边的文本

  1. uint8_t buf[4] = {1,2,3,4};
复制代码
现在我希望能在执行CREATE_ARRAY(5);时自动将第5个字节添加进去,例如:

  1. uint8_t buf[5] = {1,2,3,4,5};
复制代码
问过高手了,貌似不可能实现,不死心,在这里提问,希望能有奇迹出现。
此帖出自单片机论坛

最新回复

学习了,受教了,内容丰富,值得一看!   详情 回复 发表于 2023-11-28 21:53
点赞 关注
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 

回复
举报

2549

帖子

0

TA的资源

五彩晶圆(初级)

沙发
 
话说以前上学那会也想过这种问题,这种数组多节约空间啊,现在想想那会。。。
此帖出自单片机论坛
 
 

回复

420

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
c/c++ 不可能实现。其他语言也许可以
此帖出自单片机论坛
 
 
 

回复

1801

帖子

0

TA的资源

五彩晶圆(初级)

4
 
按照我目前的认知,我也认为不可能实现
此帖出自单片机论坛
 
 
 

回复

1801

帖子

0

TA的资源

五彩晶圆(初级)

5
 
按照我目前的认知,我也认为不可能实现,虽然我是菜鸟
此帖出自单片机论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

6
 
这是不可能的

第一个最根本的,C语言不存在动态数组,就是说,定义时必须明确数组大小,并且此后都没办法改变这个数组的大小;
第二,照你这么用这个宏,你在第二次添加时,就变成了重复定义。

其实这个地方,我的建议就是。
直接用 malloc/free函数完成;

假如是单片机环境,不适合大量使用。
不妨自己构造一个 栈区。这个涉及内存管理,事情可复杂可简单,但总之就是麻烦事一桩。

在没必要的情况下大可不必如此。

假如代码中出现了 这种情况下很麻烦很拗口的使用情形,那就考虑重新思索如何改进实现方案。

山不转水转。
没有人说,如果不存在动态数组或者 动态分配 就活不了的实现方案的

此帖出自单片机论坛

点评

>>>C语言不存在动态数组,就是说,定义时必须明确数组大小 动态数组 C99可以用在函数里,x未知 int stupid(int x) { int me[x] = {0}; ...... }  详情 回复 发表于 2015-4-21 15:06
这个不同于动态数组,使用宏创建数据在编译前数组的大小就已经确定了。 这么提问是为了简化问题,让看的人容易理解,其实我是想实现这样的功能。 例如BLE代码里有这样一段代码 "SimpleBLEBroadcaster"这样的  详情 回复 发表于 2015-4-21 12:32
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

1891

帖子

2

TA的资源

纯净的硅(中级)

7
 
有点厉害。。。
此帖出自单片机论坛
 
个人签名
分享铸就美好未来。。。




 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

8
 
楼上的说,C++也不行
其实,,C++是可以的,C++可以用 new方法,不过在我眼里,它的数组已经等同于指针了。虽然我没研究过它里面的实现方法,但显然那和C的实现方案不是一回事。
此帖出自单片机论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

9805

帖子

24

TA的资源

版主

9
 
本帖最后由 littleshrimp 于 2015-4-21 13:57 编辑
辛昕 发表于 2015-4-21 11:28
这是不可能的

第一个最根本的,C语言不存在动态数组,就是说,定义时必须明确数组大小,并且此后都没办法改变这个数组的大小;
第二,照你这么用这个宏,你在第二次添加时,就变成了重复定义。

其实这个地方,我的建议就是。
直接用 malloc/free函数完成;

假如是单片机环境,不适合大量使用。
不妨自己构造一个 栈区。这个涉及内存管理,事情可复杂可简单,但总之就是麻烦事一桩。

在没必要的情况下大可不必如此。

假如代码中出现了 这种情况下很麻烦很拗口的使用情形,那就考虑重新思索如何改进实现方案。

山不转水转。
没有人说,如果不存在动态数组或者 动态分配 就活不了的实现方案的

这个不同于动态数组,使用宏创建数据在编译前数组的大小就已经确定了。
这么提问是为了简化问题,让看的人容易理解,其实我是想实现这样的功能。
例如BLE代码里有这样一段代码



  1. // GAP - SCAN RSP data (max size = 31 bytes)
  2. static uint8 scanRspData[] =
  3. {
  4.   // complete name
  5.   0x15,   // length of this data
  6.   GAP_ADTYPE_LOCAL_NAME_COMPLETE,
  7.   0x53,   // 'S'
  8.   0x69,   // 'i'
  9.   0x6d,   // 'm'
  10.   0x70,   // 'p'
  11.   0x6c,   // 'l'
  12.   0x65,   // 'e'
  13.   0x42,   // 'B'
  14.   0x4c,   // 'L'
  15.   0x45,   // 'E'
  16.   0x42,   // 'B'
  17.   0x72,   // 'r'
  18.   0x6f,   // 'o'
  19.   0x61,   // 'a'
  20.   0x64,   // 'd'
  21.   0x63,   // 'c'
  22.   0x61,   // 'a'
  23.   0x73,   // 's'
  24.   0x74,   // 't'
  25.   0x65,   // 'e'
  26.   0x72,   // 'r'

  27.   // Tx power level
  28.   0x02,   // length of this data
  29.   GAP_ADTYPE_POWER_LEVEL,
  30.   0       // 0dBm  
  31. };

复制代码


"SimpleBLEBroadcaster"这样的代码要一个一个敲到数组里,很麻烦。

而使用下边这种方法又不被允许

  1. static uint8 scanRspData[] =
  2. {
  3.   // complete name
  4.   0x15,   // length of this data
  5.   GAP_ADTYPE_LOCAL_NAME_COMPLETE,
  6.   "SimpleBLEBroadcaster",
  7.   // Tx power level
  8.   0x02,   // length of this data
  9.   GAP_ADTYPE_POWER_LEVEL,
  10.   0       // 0dBm  
  11. };
复制代码

我能想到比较好的方法就是


  1. static uint8 scanRspData[] =
  2. {
  3.   // complete name
  4.   0x15,   // length of this data
  5.   GAP_ADTYPE_LOCAL_NAME_COMPLETE,
  6.   "SimpleBLEBroadcaster"[0],
  7.   "SimpleBLEBroadcaster"[1],
  8.   "SimpleBLEBroadcaster"[2],
  9.   "SimpleBLEBroadcaster"[3],
  10.   "SimpleBLEBroadcaster"[n],
  11.   // Tx power level
  12.   0x02,   // length of this data
  13.   GAP_ADTYPE_POWER_LEVEL,
  14.   0       // 0dBm  
  15. };
复制代码

但这样还是比较麻烦,所以如果能实现上边的功能我就可以把代码写成这样

  1. #define STRINGARRAY(str,count)  \
  2. str##[0],\
  3. str##[1],\
  4. str##[3],\
  5. str##[count - 1],
复制代码

然后这样调用


  1. static uint8 scanRspData[] =
  2. {
  3.   // complete name
  4.   0x15,   // length of this data
  5.   GAP_ADTYPE_LOCAL_NAME_COMPLETE,
  6.   STRINGARRAY("SimpleBLEBroadcaster",20),
  7.   // Tx power level
  8.   0x02,   // length of this data
  9.   GAP_ADTYPE_POWER_LEVEL,
  10.   0       // 0dBm  
  11. };
复制代码





此帖出自单片机论坛
 
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 

回复

4008

帖子

0

TA的资源

版主

10
 
这个是可以实现的,以前整过类似的功能,需要另外定义一个带_的宏函数可以将字符再转化为数字参数,不过你这个多行没想好怎么办
此帖出自单片机论坛

点评

换行只是为了看起来方便,单行也可以的,如果能让 uint8_t buf[5] = {1,2,3,4,5}; 大括号内的数值随着传入参数的大小变化就成功了。 例如传入的参数是6 uint8_t buf[6] = {1,2,3,4,5,6};  详情 回复 发表于 2015-4-21 14:00
 
 
 

回复

9805

帖子

24

TA的资源

版主

11
 
huo_hu 发表于 2015-4-21 13:25
这个是可以实现的,以前整过类似的功能,需要另外定义一个带_的宏函数可以将字符再转化为数字参数,不过你这个多行没想好怎么办

换行只是为了看起来方便,单行也可以的,如果能让
uint8_t buf[5] = {1,2,3,4,5};

大括号内的数值随着传入参数的大小变化就成功了。

例如传入的参数是6

uint8_t buf[6] = {1,2,3,4,5,6};
此帖出自单片机论坛
 
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 

回复

7671

帖子

2

TA的资源

五彩晶圆(高级)

12
 
本帖最后由 freebsder 于 2015-4-21 15:08 编辑

ISO宏没办法递归,所以只好自己include自己来递归。借助gcc的扩展来结束递归。
不过,话说,你确定 "SimpleBLEBroadcaster"[0], 这种形式可以初始化数组?
  1. // res.h
  2. #if (__INCLUDE_LEVEL__ == 1)
  3.     int buffer[NEST] = {
  4.         __INCLUDE_LEVEL__ - 1,
  5. #include "res.h"
  6. #elif (__INCLUDE_LEVEL__ > NEST)
  7.     };
  8. #else
  9.         __INCLUDE_LEVEL__ - 1,
  10. #include "res.h"
  11. #endif
复制代码
  1. // res.c
  2. #define NEST    4        // <---- change me
  3. #include "res.h"
  4. int main(void)
  5. {
  6.         for(int x = 0; x < sizeof(buffer)/sizeof(buffer[0]); x++)
  7.                 printf("%d\n", buffer[x]);
  8. }
复制代码



此帖出自单片机论坛

点评

"SimpleBLEBroadcaster"[0]在IAR和MDK中都可以正常使用。 你的参考代码也能在IAR和MDK平台下运行吗?我刚刚试过两个平台,都错在对__INCLUDE_LEVEL__ 减 1这里。  详情 回复 发表于 2015-4-21 15:38
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

2

帖子

1

TA的资源

一粒金砂(初级)

13
 
这个问题我今晚思考看看如何解决
此帖出自单片机论坛
 
 
 

回复

7671

帖子

2

TA的资源

五彩晶圆(高级)

14
 
辛昕 发表于 2015-4-21 11:28
这是不可能的

第一个最根本的,C语言不存在动态数组,就是说,定义时必须明确数组大小,并且此后都没办法改变这个数组的大小;
第二,照你这么用这个宏,你在第二次添加时,就变成了重复定义。

其实这个地方,我的建议就是。
直接用 malloc/free函数完成;

假如是单片机环境,不适合大量使用。
不妨自己构造一个 栈区。这个涉及内存管理,事情可复杂可简单,但总之就是麻烦事一桩。

在没必要的情况下大可不必如此。

假如代码中出现了 这种情况下很麻烦很拗口的使用情形,那就考虑重新思索如何改进实现方案。

山不转水转。
没有人说,如果不存在动态数组或者 动态分配 就活不了的实现方案的

>>>C语言不存在动态数组,就是说,定义时必须明确数组大小

动态数组 C99可以用在函数里,x未知
int stupid(int x)
{
    int me[x] = {0};
    ......
}


此帖出自单片机论坛
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

6111

帖子

4

TA的资源

版主

15
 
把字符串倒到数组里. strcpy应该就是干这事的, sprintf(....)应该也有这个能力吧.可以试下.
此帖出自单片机论坛

点评

如果把字符串存到数组里,使用strcopy就需要在buf里预留一段和字符串等长的空间用来存放数据,这样使用起来还是很麻烦。  详情 回复 发表于 2015-4-21 15:40
 
 
 

回复

9805

帖子

24

TA的资源

版主

16
 
freebsder 发表于 2015-4-21 14:40
ISO宏没办法递归,所以只好自己include自己来递归。借助gcc的扩展来结束递归。
不过,话说,你确定 "SimpleBLEBroadcaster"[0], 这种形式可以初始化数组?

"SimpleBLEBroadcaster"[0]在IAR和MDK中都可以正常使用。

你的参考代码也能在IAR和MDK平台下运行吗?我刚刚试过两个平台,都错在对__INCLUDE_LEVEL__ 减 1这里。

此帖出自单片机论坛

点评

》》》 "SimpleBLEBroadcaster"[0]在IAR和MDK中都可以正常使用。 哦,还真行,不过这个非标准的,IAR扩展的,把扩展关掉就不行了。。。 [attachimg]195426[/attachimg]  详情 回复 发表于 2015-4-21 17:13
IAR 试试这个:  详情 回复 发表于 2015-4-21 16:38
 
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 

回复

9805

帖子

24

TA的资源

版主

17
 
damiaa 发表于 2015-4-21 15:30
把字符串倒到数组里. strcpy应该就是干这事的, sprintf(....)应该也有这个能力吧.可以试下.

如果把字符串存到数组里,使用strcopy就需要在buf里预留一段和字符串等长的空间用来存放数据,这样使用起来还是很麻烦。
此帖出自单片机论坛

点评

穷举算么?? #include "stdio.h" unsigned char aa[]="开"; int i=-122113; #define A_1(s) unsigned int buf[]={s[0]}; #define A_2(s) unsigned int buf[]={s[0],s[1]}; #define A_3(s) unsigned int buf  详情 回复 发表于 2015-4-21 16:18
 
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 

回复

165

帖子

0

TA的资源

一粒金砂(中级)

18
 
本帖最后由 EETUX 于 2015-4-21 16:24 编辑


#include "stdio.h"

#define A_1(s) unsigned int buf[]={s[0]};

#define A_2(s) unsigned int buf[]={s[0],s[1]};

#define A_3(s) unsigned int buf[]={s[0],s[1],s[2]};

#define A_4(s) unsigned int buf[]={s[0],s[1],s[2],s[3]};

#define A_5(s) unsigned int buf[]={s[0],s[1],s[2],s[3],s[4]};

#define A_6(s) unsigned int buf[]={s[0],s[1],s[2],s[3],s[4],s[5]};

//...



#define B(x,y) AA(x,y);

#define AA(x,y) A_##x(y)

int main()

{

   B(5,"HELLO");

   printf("%c %c %c %c %c",buf[0],buf[1],buf[2],buf[3],buf[4]);

   getchar();  

}
此帖出自单片机论坛
 
 
 

回复

7671

帖子

2

TA的资源

五彩晶圆(高级)

19
 
本帖最后由 freebsder 于 2015-4-21 16:49 编辑
littleshrimp 发表于 2015-4-21 15:38
"SimpleBLEBroadcaster"[0]在IAR和MDK中都可以正常使用。

你的参考代码也能在IAR和MDK平台下运行吗?我刚刚试过两个平台,都错在对__INCLUDE_LEVEL__ 减 1这里。

IAR 试试这个:

  1. // res.h

  2.         __COUNTER__/2,
  3. #if (__COUNTER__ <= NEST*2)
  4. #include "res.h"
  5. #endif
复制代码
  1. // res.c
  2. #define NEST    4
  3. int buffer[NEST] = {
  4. #include "res.h"
  5. };

  6. int main(void)
  7. {
  8.         for(int x = 0; x < sizeof(buffer)/sizeof(buffer[0]); x++)
  9.                 printf("%d\n", buffer[x]);
  10. }
复制代码




此帖出自单片机论坛

点评

和刚才的代码提示错误相同,IAR,MDK都提示  详情 回复 发表于 2015-4-21 16:54
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

9805

帖子

24

TA的资源

版主

20
 

和刚才的代码提示错误相同,IAR,MDK都提示

  1. this declaration has no storage class or type specifier
复制代码


此帖出自单片机论坛

点评

把int buffer[NEST]改成 int buffer[] IAR的扩展初始化只支持后一种形式。。。 [attachimg]195425[/attachimg]  详情 回复 发表于 2015-4-21 17:08
 
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表