经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
C语言中#define在多行宏定义出错的原因及分析
来源:jb51  时间:2023/2/27 9:41:56  对本文有异议

C语言中#define在多行宏定义出错的原因

1.第一种错误

  1. #include<stdio.h>
  2. #define echange(a,b) {\/*宏定义中允许包含多行命令的情形,此时必须在最右边加上"\"*/
  3. ?int t;?t=a;?a=b;?b=t;}
  4. main()
  5. {
  6. ?int c, d;
  7. ?c = 2;
  8. ?d = 3;
  9. ?printf("%d %d\n", c, d);
  10. ?echange(c,d)
  11. ?printf("%d %d\n", c, d);
  12. ?return 0;
  13. }

在用#define进行多行宏定义时,注释要放在"\"之前

2.第二种错误

  1. #include<stdio.h>
  2. #define echange(a,b) {/*宏定义中允许包含两道衣裳命令的情形,此时必须在最右边加上"\"*/?int t;?t=a;?a=b;?b=t;}/*在最后一行多加了一个"\"*/main()
  3. {
  4. ?int c, d;
  5. ?c = 2;
  6. ?d = 3;
  7. ?printf("%d %d\n", c, d);
  8. ?echange(c,d)
  9. ?printf("%d %d\n", c, d);
  10. ?return 0;
  11. }

在用#define进行多行宏定义时,在最后一行加上"\“,我们使用#define进行多行定义时,默认最后一个”\“的下一行也属于宏定义范围,去掉最后一行的”\"即可

以下是代码的正确形式

  1. #include<stdio.h>
  2. #define echange(a,b) {/*宏定义中允许包含两道衣裳命令的情形,此时必须在最右边加上"\"*/?int t;?t=a;?a=b;?b=t;}
  3. main()
  4. {
  5. ?int c, d;
  6. ?c = 2;
  7. ?d = 3;
  8. ?printf("%d %d\n", c, d);
  9. ?echange(c,d)
  10. ?printf("%d %d\n", c, d);
  11. ?return 0;
  12. }

使用#define宏定义的几个小技巧

1.调试开关

有时候编写程序时为方便查找错误,会在很多地方加上串口打印语句直观查看程序哪里出错。

但是,串口的输出是需要时间的,在项目基本完成时,就需要将这些打印关闭,但是一行一行的注释掉费时费力,不现实。

这时可以使用宏来当做一个"开关",直接操作这个宏就可以实现打印的开关,例如:

  1. //#define?? ?DEBUG(...)
  2. #define?? ??? ?DEBUG?? ?printf

另外,还可以使用几个预定义的宏进行辅助:

  1. __FILE__?? ??? ??? ?// 文件
  2. __FUNCTION__?? ??? ?// 函数
  3. __LINE__?? ??? ??? ?// 行号
  4.  
  5. DEBUG("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

2.条件编译

当程序为了适配更多不同的环境时,还可以使用条件宏来选择不同的代码模块:

  1. #if 1
  2. ?? ?printf("Hello!\n");
  3. #else
  4. ?? ?printf("Hi!\n");
  5. #endif

3.宏实现函数

交换两个数:

  1. #define swap(a,b) ?? ?((a)=(a)+(b);(b)=(a)-(b);(a)=(a)-(b))

比较两个数并且返回最小的数:

  1. #define MIN(a,b) ?? ?((a)<(b)?(a):(b))

求数组元素个数:

  1. #define LENGTH(array)?? ?(sizeof(array) / sizeof(array[0]))

4.跨行宏定义

  1. #define?? ?SWAP(a,b)?? ?do { ?? ??? ? ? ??? ??? ??? ?int t = 0;?? ??? ??? ??? ??? ??? ?t = a; ?? ??? ??? ??? ??? ??? ?a = b; ?? ??? ??? ??? ??? ??? ?b = t; ?? ??? ??? ??? ??? ?} while(0)

细心的你可能已经注意到以上宏末尾都没有带分号“;”

5.防止头文件被重复包含

  1. #ifndef __TEST_H?
  2. #define __TEST_H?
  3. ?? ?// 头文件内容?
  4. #endif

6.带参宏与带参函数的区别

  • 1.宏会在编译器在对源代码进行编译的时候进行简单替换,不会进行任何逻辑检测,即简单代码复制而已;
  • 2.宏进行定义时不会考虑参数的类型;
  • 3.参数宏的使用会使具有同一作用的代码块在目标文件中存在多个副本,即会增长目标文件的大小;
  • 4.参数宏的运行速度会比函数快,因为不需要参数压栈/出栈操作;
  • 5.参数宏在定义时要多加小心,多加括号;
  • 6.函数只在目标文件中存在一处,比较节省程序空间;
  • 7.函数的调用会牵扯到参数的传递,压栈/出栈操作,速度相对较慢;
  • 8.函数的参数存在传值和传地址(指针)的问题,参数宏不存在;

7.注意事项

  • 1.宏定义不会对引号内的参数进行替换;
  • 2.若要替换,可以在参数前面加上’#’转换成“字符串”,如:
  1. #define dprint(expr) printf(#expr " = %d\n", expr)

使用dprint(x/y)就被替换成:

  1. printf("x/y" " = %g\n", x/y);

  1. printf("x/y = %g\n", x/y);

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号