目录

1.宏格式:

2.无参宏详解:

3.宏和typedef:

4.有参宏详解:

5.无参宏说明:

6.有参宏说明:

7.宏的优点:

8.宏的缺点:

9.define与const的区别的简单总结:


1.宏格式:

  1. 每个#define行由三部分组成:第一部分是指令 #define 自身,“#”表示这是一条预处理命令,“define”为宏命令。
  2. 第二部分为宏,一般为缩略语,其名称(宏名)一般大写,而且不能有空格,遵循C变量命令规则。
  3. “替换文本”可以是任意常数、表达式、字符串等。
  4. 在预处理工作过程中,代码中所有出现的“宏名”,都会被“替换文本”替换。
  5. 这个替换的过程被称为“宏代换”或“宏展开”(macro expansion)。
  6. “宏代换”是由预处理程序自动完成的。在C语言中,“宏”分为两种:无参数 和 有参数。

2.无参宏详解:

  1. 无参宏是指宏名之后不带参数,最简单的宏就是无参宏。
  2. 一种最简单的宏的形式如下:       #define 宏名 替换文本
  3. #define M 10               // 宏定义
    #define PI 3.14            //宏定义#define H hi;int arr[M];                  // 会被替换为: int a[5]
    int b = M;                 // 会被替换为: int b = 5
    printf("%d",H) ;           //会输出: hi;
    printf("PI = %.2f\n", PI); // 输出结果为: PI = 3.14
    
  4. 注意宏不是语句,结尾不需要加“;”,否则会被替换进程序中,如上例: 输出: hi;
  5. 如果要写宏不止一行,则在结尾加反斜线符号使得多行能连接上,如
  6. #define HELLO "hello the wo\rld"printf("HELLO is %s\n", HELLO);
    //输出结果为: HELLO is hello the wo  rld 
  7. 宏可以嵌套,但不参与运算:
    #define M 5                 // 宏定义
    #define MM M * M            // 宏的嵌套printf("MM = %d\n", MM);    // MM 被替换为: MM = M * M, 然后又变成 MM = 5 * 5
    
  8. 宏定义必须写在函数之外,其作用域是 #define 开始,到源程序结束。如果要提前结束它的作用域则用 #undef 命令,如:
  9. #define M 5                 // 宏定义
    printf("M = %d\n", M);      // 输出结果为: M = 5
    #define M 100               // 取消宏定义
    printf("M = %d\n", M);      // error:… main.c:138:24: Use of undeclared identifier 'M'
    

    3.宏和typedef:

  1. 宏定义只是简单的字符串代换,在预处理阶段完成。
  2. 而typede不是简单的字符串代换,而是可以用来做类型说明符的重命名的,类型的别名可以具有类型定义说明的功能,在编译阶段完成的。

4.有参宏详解:

  1. C语言中宏是可以有参数的,这样的宏就成了外形与函数相似的类函数宏(function-like macro),如:
  2. 和函数类似,在宏定义中的参数成为形式参数,在宏调用中的参数成为实际参数。
  3. 而且和无参宏不同的一点是,有参宏在调用中,不仅要进行宏展开,而且还要用实参去替换形参。
#define COUNT(M) M * M               //定义有参宏
int x = 6;
printf("COUNT = %d\n", COUNT(x + 1));// 输出结果: COUNT = 13
printf("COUNT = %d\n", COUNT(++x));  // 输出结果: COUNT = 56                                                                                               //warning:... main.c:161:34: Multiple unsequenced             modifications to 'x'

这两个结果和调用函数的方法的结果差别很大,因为如果是像函数那样的话,COUNT(x + 1)应该相当于COUNT(7),结果应该是 7 * 7 = 49,但输出结果却是21。原因在于,预处理器不进行技术,只是进行字符串替换,而且也不会自动加上括号(),所以COUNT(x + 1)被替换为 COUNT(x + 1 * x + 1),代入 x = 6,即为 6 + 1 * 6 + 1 = 13。而解决办法则是:尽量用括号把整个替换文本及其中的每个参数括起来。

5.无参宏说明:

说明:

  (1)宏名一般用大写。

   (2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义。

   (3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。

  (4)宏定义末尾不加分号。

  (5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。

  (6)可以用#undef命令终止宏定义的作用域。

  (7)宏定义可以嵌套。

  (8)字符串" "中永远不包含宏。

  (9)宏定义不分配内存,变量定义分配内存。

  (10)宏定义不存在类型问题,它的参数也是无类型的。

6.有参宏说明:

1)实参如果是表达式容易出问题
    #define S(r) r*r
    area=S(a+b);第一步换为area=r*r;第二步被换为area=a+b*a+b;
    正确的宏定义是#define S(r) ((r)*(r))
  (2)宏名和参数的括号间不能有空格。
  (3)宏替换只作替换,不做计算,不做表达式求解。
  (4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存。
  (5)宏的哑实结合不存在类型,也没有类型转换。
  (6)函数只有一个返回值,利用宏则可以设法得到多个值。
  (7)宏展开使源程序变长,函数调用不会。

 (8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)。

7.宏的优点:

.1.增强代码的复用性。

2.提高性能。

8.宏的缺点:

  1. 无法对宏定义中的变量进行类型检查
  2. 未加括号带来的边界效应;
  3. 在宏定义中出现++或—之类的操作符的时候,即使加括号,也无法避免其中的问题;
  4. 不方便调试,在预处理阶段就进行了替换;
  5. 代码可读性差,维护性差,容易误用;

9.define与const的区别的简单总结:

  1. define定义的变量,是Compile-Time时期的变量,系统在编译时候,就将其全部替换,而不会对其变量进行类型等属性检查,相对不是很安全,可能存在潜在的问题,而没有发现.
  2. 正因为其仅仅是编译时期替换,所以其定义的变量,是不会在运行时候分配内存的,不占用内存空间.
  3. const定义的变量,是 Run-Time时期的变量,如果类型不匹配,系统在运行时候,就会发现并提示或报错,对应的,const变量在运行时期,也是一种变量,系统会为其分配内存.
  • 参考文章链接:
  1. https://blog.csdn.net/u012782049/article/details/38975591
  2. http://blog.csdn.net/imgosty/article/details/81901183
  3. http://blog.csdn.net/freeking101/article/details/79066033

【C++---10】有参宏,无参宏,宏的优缺点相关推荐

  1. IDEA try catch快捷键、 快速生成get set 方法快捷键、快速生成有参和无参构造方法快捷键

    IDEA try catch快捷键. 快速生成get set 方法快捷键.快速生成有参和无参构造方法 1. try catch快捷键 小伙伴们在写代码的过程中,有时需要抛出异常,手写太浪费时间,我们想 ...

  2. IDEA 工具中 如何生成有参和无参的构造方法

    IDEA 工具中 如何生成有参和无参的构造方法 按下Alt+ins键

  3. wait与sleep的讲解(wait有参及无参区别)

    目录 1. wait() 与wait( long timeout ) 区别 2. wait(0) 与 sleep(0)区别 3. wait 和sleep 释放代码 4.  wait 与 sleep 区 ...

  4. 三天实现独立分析宏基因组数据(有参、无参和分箱等)

    在广大粉丝的期待下,<生信宝典>联合<宏基因组>在2019年11月1-3日,北京鼓楼推出<宏基因组分析>专题培训第六期,为大家提供一条走进生信大门的捷径.为同行提供 ...

  5. 构造器(有参、无参)

    构造器: 就是和类名相同但无返回类型的方法.用于当前或某一对象的实例化,并将当前或某一对象返回.无参构造:1.如果使用new关键字实际上是调用无参构造器:2.无参构造往往是为了初始化一些值.有参构造: ...

  6. C++ 有参构造 无参构造 拷贝构造 以及参数化列表 成员对象之间的执行关系

    #include <iostream> #include <string> using namespace std; class Phone { public:string m ...

  7. python有参函数和无参函数的区别_构造函数的有参和无参的区别,构造函数的参数是派什么用场的?...

    展开全部 区别: 1.如果在创建对象时不写参数,调用的就32313133353236313431303231363533e58685e5aeb931333366303861是无参的构造方法.可是如果你 ...

  8. Qt调用python有参和无参方法,取方法返回值

    环境准备 QT版本:4.8.5    下载地址:http://download.qt.io/archive/qt/4.8/4.8.5/ MinGW编译器:MinGW 32位    下载地址:https ...

  9. java有参和无参的用处_Java对比有参数和无参数

    有参数:小括号当中有内容,当一个方法需要一些数据条件,才能完成任务的时候,就是有参数. 例如两个数字相加,必须知道两个数字是各自多少,才能相加. 无参数:小括号当中留空.一个方法不需要任何数据条件,自 ...

  10. SQL工作笔记-达梦7中存储过程相关笔记(有参、无参、变量声明)

    无参数 运行截图如下: 对应源码如下: CREATE OR REPLACE PROCEDURE "NUSP"."TESTTIME" AUTHID DEFINER ...

最新文章

  1. 012_logback中的DBAppender
  2. SAP实施顾问参与主数据搜集的四大好处
  3. PyYAML——yaml.load()警告【YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated】解决方案
  4. 解决waitfor()阻塞问题
  5. javascipt -- find方法和findIndex方法的实现
  6. 结晶紫行业调研报告 - 市场现状分析与发展前景预测
  7. termux 安装python3教程_termux怎么安装python
  8. 基于信息论的特征选择算法综述
  9. 魔兽和星际的最大差别
  10. python需要什么样的电脑_学习Python需要配备什么样的电脑
  11. 导致页面布局混乱的几个元凶
  12. DDD案例(2):从领域分析到代码实现
  13. 移动端300ms延迟_移动端延迟300ms的原因以及解决方案
  14. 计算机发展的各个阶段是以什么作为标志的,计算机发展的各个阶段是以什么作为标志的?...
  15. c语言陶陶摘苹果数组,关于新手数组:样题:陶陶摘苹果
  16. 【图文教程】注册Oculus开发者账号
  17. 大数据平台开源实施的难点
  18. 移动硬盘启动win7蓝屏7b_电脑插入移动硬盘后,只要一点击移动硬盘中的文件夹就马上蓝屏...
  19. 解决安装Ubuntu时鼠标无法移动,卡Logo的问题
  20. Excel根据出生日期和身份证使用公式计算年龄

热门文章

  1. python编写查询系统_小菜鸟的python学习之路----信息查询系统
  2. 洛谷——P1348 Couple number
  3. 使用 CUPS 命令行实用程序设置和管理打印机
  4. 数字城市厦门1+N联动执法管理系统平台测试用例【软件测试与工程】
  5. Qt zint (生成一维码/二维码)
  6. 手机耳机连台式电脑能用手机耳机说话吗?【当然可以】
  7. TMS320F2837xD和TMS320F2837xS的区别
  8. 智能汽车与Qualcomm骁龙820A
  9. java学习心得(1)
  10. DOTween的基本使用方法