#define详详详详详解

目录

一、#define定义标识符

基本的格式

注意:

二、#define定义宏

表示方式

注意点

带副作用的宏参数

三、宏与函数的对比

        【命名规定】

(扩展)#和##

1. #的作用

2. ##的作用


#define的使用方式有两种用法,分别是定义标识符定义宏

别看只有两种用法,展开来讲可有很多内容需要学习

一、#define定义标识符

基本的格式

#define             name                     stuff

 操作符    简化的表示方式     被表示的内容

一般而言,被表示的内容没有太多的限制,可表示数值关键字,甚至语句都可以

下面有几个例子可以加深理解

#define MAX 1000
#define reg register        //为关键字创建更简短的名字
#define do_forever for(;;)
#define CASE break;case     //写case语句时自动把break写上
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
                          date:%s\ttime:%s\n" ,\
                          __FILE__,__LINE__ ,  \
                          __DATE__,__TIME__ )

注意:

1. 如果定义的stuff过长,可以分成几行写,除最后一行外,每一行都要加反斜杠用来表示续写

2. 此语句是不用分号结尾的,因为define后面的内容是直接替换的,所以如果需要分号才加进去,否则有可能导致出现编译错误

以下为错误示范,注意,是错误示范!!!

#define MAX 1000;

int main()
{
    if(1)
      max = MAX;
    else
      max = 0;

    return 0;
}

 

 正确的做法仅仅是少了一个分号,失之毫厘,谬以千里呀!!

#define MAX 1000

int main()
{
    if(1)
      max = MAX;
    else
      max = 0;

    return 0;
}

 

二、#define定义宏

这个有点类似函数,但跟函数还是有一定的差异的

表示方式

#define     name(parament-list)             stuff

 操作符          表示/使用方式             被表示的内容

 *parament-list是指要使用到的一个或多个参数

这里又要注意

在定义宏的时候要尽可能给参数加括号,避免因为优先级而导致计算方式并不是自己想要的

#define SQUARE(x) x*x

int a = 5;
printf("%d\n" ,SQUARE(a + 1) );

此处打印的结果为11,而不是36

计算方式是5+1*5+1=11

如果想要结果是36的话,要如下操作

#define SQUARE(x) (x)*(x)

int a = 5;
printf("%d\n" ,SQUARE(a + 1) );

注意点

1. #define中可以出现其他#define定义的变量,但是不能出现递归 

2. 预处理器搜索#define定义的符号的时候,字符串常量的内容不被搜索

带副作用的宏参数

指运行时带有类似“++”或“--”等符号,会对参数值做出改变

当宏参数在宏的定义中多次出现时,如果参数带有副作用,那么有可能会导致不可预测的后果

示例:

#define MAX(a, b)  ( (a) > (b) ? (a) : (b) )
...
x = 5;
y = 8;
z = MAX(x++, y++);
printf("x=%d y=%d z=%d\n", x, y, z);

 MAX(a, b)  ( (a) > (b) ? (a) : (b) )

将参数替换:

MAX(x++, y++)  ( (x++) > (y++) ? (x++) : (y++) )

先判断x是否大于y,结果为假,此时x++,y++,然后运行冒号后的语句,y++,

所以x加了一次(x=6),y加了两次(y=10),z返回的是冒号后语句++之前的大小(z=9)

三、宏与函数的对比

代码长度:

宏代码使用时要插到程序中,除了小的宏,一般会加大代码的长度

函数每次调用同一份代码,简洁高效

-------------------------------------------

执行速度:

函数调用和返回有额外开销

-------------------------------------------

操作符优先级:

直接替换,可能会出现优先级预判错误

函数先求值一次再传参,结果更易预测

-------------------------------------------

带有副作用的参数:

宏:参数可能被替换在多个位置,可能有意外

函数:更易控制

-------------------------------------------

参数类型:

宏:参数与类型无关

函数:参数类型不同就是不同函数

-------------------------------------------

调试和递归

宏均不能实现

函数专属

-------------------------------------------

综上所述:

想快,想适合多种类型参数用宏,其余用函数

【命名规定】

习惯上

宏全部大写

函数不全大写

(扩展)#和##

1. #的作用

思考一个问题:如何把参数插到字符串中?

有了宏就可以相对灵活地操作了

#define PRINT(FORMAT, VALUE)\
    printf("the value is "FORMAT"\n", VALUE);
...
PRINT("%d",10);

而如果我想把宏参数变成对应的字符串呢?

就使用到“#”了

举个例子:

int i = 10;
#define PRINT(FORMAT, VALUE)\
    printf("the value of " #VALUE "is "FORMAT "\n", VALUE);
...
PRINT("%d", i+3);

最终的输出结果就是: the value of i+3 is 13

2. ##的作用

把位于两边的符号合成一个符号

用于将分离的文本片段合成标识符

举例:

#define ADD_TO_SUM(num, value) \
    sum##num += value;
...
ADD_TO_SUM(5, 10);//作用是:给sum5增加10.

注意:连接的必须是合法的标识符

你可能感兴趣的:(c语言,c++,算法,数据结构,开发语言)