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

 更新时间:2023年02月24日 16:02:51   作者:倒在路上的羊  
这篇文章主要介绍了C语言中#define在多行宏定义出错的原因及分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

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

1.第一种错误

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

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

2.第二种错误

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

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

以下是代码的正确形式

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

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

1.调试开关

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

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

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

//#define    DEBUG(...)
#define        DEBUG    printf

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

__FILE__            // 文件
__FUNCTION__        // 函数
__LINE__            // 行号

DEBUG("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

2.条件编译

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

#if 1
    printf("Hello!\n");
#else
    printf("Hi!\n");
#endif

3.宏实现函数

交换两个数:

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

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

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

求数组元素个数:

#define LENGTH(array)    (sizeof(array) / sizeof(array[0]))

4.跨行宏定义

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

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

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

#ifndef __TEST_H 
#define __TEST_H 
    // 头文件内容 
#endif

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

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

7.注意事项

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

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

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

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

总结

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

相关文章

  • C++ ffmpeg实现将视频帧转换成jpg或png等图片

    C++ ffmpeg实现将视频帧转换成jpg或png等图片

    有时播放实时流的时候有截图的需求,需要将解码出来的图片保存本地或上传服务器,这时就需要将avframe中的数据编码成png、jpg等格式的图片,我们使用ffmpeg的相关编码器就可以实现功能,下面就来讲讲具体实现方法吧
    2023-03-03
  • 赌你会懵的C语言指针进阶数组场景解析

    赌你会懵的C语言指针进阶数组场景解析

    这篇文章主要为大家介绍了关于C语言指针进阶的示例解析,来细化指针这一部分内容,现在着重把一些指针的运用情景搬出来康康,如果对指针盘的不是非常熟练,或者指针还出于入门阶段的铁子请绕道
    2022-02-02
  • C和C++如何实现互相调用详解

    C和C++如何实现互相调用详解

    在学习c++中用到一些古老的c语言库时,在工作中我们经常要使用C和C++混合编程,下面这篇文章主要给大家介绍了关于C和C++如何实现互相调用的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • 详解C++引用变量时那些你不知道的东西

    详解C++引用变量时那些你不知道的东西

    这篇文章主要为大家详细介绍了C++引用变量时那些你不知道的东西——引用变量延迟绑定,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-11-11
  • 浅谈C++日志系统log4cxx的使用小结详解

    浅谈C++日志系统log4cxx的使用小结详解

    本篇文章是对C++日志系统log4cxx的使用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • Prim(普里姆)算法求最小生成树的思想及C语言实例讲解

    Prim(普里姆)算法求最小生成树的思想及C语言实例讲解

    Prim算法能够在带权的图中搜索出最小生成树,这也是各大ACM和面试及考研题目中的热点,下面我们就来详细看一下Prim(普里姆)算法求最小生成树的思想及C语言实例讲解
    2016-06-06
  • 浅析C++中的重载,隐藏和覆盖

    浅析C++中的重载,隐藏和覆盖

    在C++语言中,函数扮演着很重要的角色,不管面向过程设计,还是基于对象设计。本文主要为大家介绍了函数中重载、覆盖和隐藏的相关知识,感兴趣的小伙伴可以了解一下
    2022-12-12
  • 纯C语言:分治问题源码分享

    纯C语言:分治问题源码分享

    这篇文章主要介绍了纯C语言:分治问题源码,有需要的朋友可以参考一下
    2014-01-01
  • C++ 数据结构之布隆过滤器

    C++ 数据结构之布隆过滤器

    这篇文章主要介绍了C++ 数据结构之布隆过滤器的相关资料,需要的朋友可以参考下
    2017-06-06
  • VSstudio中scanf返回值被忽略的原因及解决方法(推荐)

    VSstudio中scanf返回值被忽略的原因及解决方法(推荐)

    这篇文章主要介绍了VSstudio中scanf返回值被忽略的原因及其解决方法,scanf返回值被忽略,接下来我就告诉大家该如何解决这个问题,需要的朋友可以参考下
    2022-09-09

最新评论