【C++---10】有参宏,无参宏,宏的优缺点

目录

 

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变量在运行时期,也是一种变量,系统会为其分配内存.
  4.  

 

  • 参考文章链接:
  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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值