#define与函数、typedef、enum、const的区别

#define 替换

在程序中扩展#define定义符号和宏时,需要涉及几个步骤。

  • 在调用宏时,首先对参数进行行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
  • 替换文本随后被插⼊入到程序中原来文本的位置。对于宏,参数名被他们的值替换。
  • 最后,再次对结果文件进行行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。

注意:

  • 宏参数和#define 定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归
  • 当预处理理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索

宏和函数

  当我们通过学习C语言逐步理解了宏和函数的作用后,不免会产生这样的疑惑:宏和函数有什么区别?为什么有的代码在实现功能时用到的是宏,有的代码中却用到的是函数?
  就我们目前看到的这些代码来看,也有不少用到宏的地方,比如【可变参数列表】这一文中提到的va_start,va_arg,va_end这三个宏,它们为什么要将他们写成宏而不是函数呢?
  这里我要介绍宏对比函数一个最大的区别,就是宏是类型无关的,宏的参数可以传递任意类型参数,甚至可以传递类型名

  这个宏的第二个参数传递的就是int这个类型名,而如果换成函数的话,没有一个形参可以接收这个int类型吧?
  
  下面我再给大家介绍宏对比函数第二个区别: 宏比函数在程序的规模和速度方面更胜一筹
 
  认识过栈帧的创建与销毁,相信大家应该对函数创建时的要执行的汇编语句都有点印象,那么想必大家也能想到函数在创建时不仅会在内存中创建一定的空间,而且会有传递和返回参数这么一个过程,它的效率必然是比宏要慢很多(因为宏作用时是在预编译阶段完成替换而已,并不会创建多余空间或是传递多余参数)。
  
  那么说了这么多宏的优点,宏难道可以可以完全替代函数吗?
 
  答案当然是  不能

宏传参时可能出现的副作用

当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候 就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。

 #define COUNT(A, B) (A * B + B)  

    int a = 10;
    int b = 20;
    int ret = COUNT(a+b, a+b);
    printf("%d\n", ret);

程序执行后:
遇到宏直接替换,程序执行相当于:int ret = a+b*a+b+a+b
对于宏可能出现的副作用,建议对宏内的参数多加括号

 #define COUNT(A, B) ((A) * (B) + (B))  

    int a = 10;
    int b = 20;
    int ret = COUNT(a+b, a+b);
    printf("%d\n", ret);

程序执行后:
遇到宏直接替换,程序执行相当于:int ret =((a+b)*(a+b)+(a+b))

宏和函数的区别

#define和typedef

  • #define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不关含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错。例如
#define PI 3.1415926 

程序中的:area=PI*r*r会替换为3.1415926*r*r

  • typedef是在编译时处理的。它在自己的作用域内给一个已经存在的类型一个别名
  • typedef int * int_ptr;#define int_ptr int *
    作用都是用int_ptr代表 int * ,但是二者不同,正如前面所说 ,#define在预处理 时进行简单的替换,而typedef不是简单替换 ,而是采用如同定义变量的方法那样来声明一种类型。

#define和typedef

typedef int * p_t;
#define INT int *

int main()
{
    p_t a,b;
    INT c,d;

此时,a,b,c均为整型指针,但d为整型

#denfine和enum的区别

enum和#define定义的标识符比较,枚举有类型检查,更加严谨。

#denfine宏常量和const常量的区别

C++ 语言可以用const 来定义常量,也可以用#define 来定义常量。但是前者比后者有更多的优点:
(1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
(2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。规则5-2-1:在C++ 程序中只使用const 常量而不使用宏常量,即const 常量完全取代宏常量。

define宏定义和const常变量用法区别

  • define是宏定义,程序在预处理阶段将用define定义的内容进行了替换。因此程序运行时,常量表中并没有用define定义的常量,系统不为它分配内存。const定义的常量,在程序运行时在常量表中,系统为它分配内存。

  • define定义的常量,预处理时只是直接进行了替换。所以编译时不能进行数据类型检验。const定义的常量,在编译时进行严格的类型检验,可以避免出错。

  • define定义表达式时要注意“边缘效应”,

猜你喜欢

转载自blog.csdn.net/sifanchao/article/details/80331352