基本语法:
#define name( parament-list ) stuff
其中的 parament-list 是⼀个由逗号隔开的符号表,它们可能出现在stuff中。
简单的说就是和函数差不多,在宏里面写一个类似于函数的计算方法,但是比函数运行的速度要快。
#define宏替换的使用
在C语言中,`#define` 预处理器指令用于定义宏,这些宏可以在编译时被预处理器替换为指定的文本。
下面是一些使用 `#define` 宏替换的例子:
1. **定义一个简单的宏**:
```c
#define PI 3.14159
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))
```
在这些例子中,`PI` 被定义为圆周率的值,`MIN` 宏接受两个参数并返回它们中的最小值,`SQUARE` 宏接受一个参数并返回其平方。
2. **使用宏替换字符串**:
```c
#define GREETING "你好,世界!"
```
这个宏可以在代码中任何需要字符串 "你好,世界!" 的地方使用。
3. **使用宏替换代码块**:
```c
#define PRINT_INT(i) printf("整数:%d\n", i)
```
这个宏可以在代码中任何需要打印整数的地方使用。
4. **在宏中使用续行符号**:
```c
#define LONG_MACRO(x, y) x ## y \
x ## _ ## y \
y ## _ ## x
```
这个宏使用了续行符号 `\` 来将宏的定义延续到下一行。它将生成三个串联的字符串。
5. **在宏中包含条件编译**:
```c
#define DEBUG 1
#if DEBUG
#define LOG(msg) printf("调试信息:%s\n", msg)
#else
#define LOG(msg)
#endif
```
这里我们主要讲解1,4。因为2,3,5基本上就是定义常量,直接进行替换就可以。
下面是一个完整的例子,展示了如何在 `main` 函数中使用这些宏:
```c
#include <stdio.h>
#define PI 3.14159
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))
#define GREETING "你好,世界!"
#define PRINT_INT(i) printf("整数:%d\n", i)
int main() {
double radius = 10.0;
double area = PI * SQUARE(radius);//
printf("圆的面积是:%.2f\n", area);
int a = 5;
int b = 10;
PRINT_INT(MIN(a, b));
printf(GREETING "\n");
return 0;
}
```
使用详解1
在这个例子中,我们使用了多个宏来简化代码,并提高了代码的可读性和可维护性。
宏定义,也就是squart(x) 就散是x乘x
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MUL(x) ((x)*(x))
//宏的使用有很多小的点
//1,宏是直接进行替换的,所以在需要进行宏运算的时候,要尽量多加上括号,防止因为优先级的问题导致使用错误
int main()
{
int a = 3;
int ret = MUL(a);
printf("%d ", ret);
return 0;
}
使用详解2
这里打印出来是7
宏是直接替换的 这里就变成了3+1*3+1=3+3+1=7
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MUL(x) ((x)*(x))
#define MULL(x) x+1*x+1
//宏的使用有很多小的点
//1,宏是直接进行替换的,所以在需要进行宏运算的时候,要尽量多加上括号,防止因为优先级的问题导致使用错误
int main()
{
int a = 3;
int ret = MUL(a);
int ret1 = MULL(a);
printf("%d %d", ret, ret1);
return 0;
}
预处理阶段宏定义
我们这里看一下预处理
如果想变成36 我们可以加上括号
所以可以书写乘((x)*(X))这样 书写宏的时候不要吝啬括号
所以
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#define的副作用 (带有副作⽤的宏参数)
++是有副作用的 这就是带有副作用
x+1;//不带副作⽤
x++;//带有副作⽤
副作用宏举例1
这里解释一下为什么有副作用
就比如下面的这个例子 ,首先什么定义一个宏,这里是一个三目操作符。如果我们传递的时候,把++传递过去就会导致宏的直接替换。
#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);//输出的结果是什么?
也就是变成了
1,我们要先把++,替换进去。
2,z = ( (x++) > (y++) ? (x++) : (y++));已知 x = 5;y = 8;
3,得到z = ( (x=5++) > (y=8++) ? (x++) : (y++));这里因为是后置++,所以是先比较后++,5大于8
4,所以此时x=6,y=9,但是这里是一个三目操作符,所以会导致的情况就是满足y++的条件,所以z=(y=8++)++=9,。
5,因为后置++,就是这个运算结束之后才会进行++,这里y++两次,所以y=10,进行z判断的时候,y++一次,所以z=9
6,这里我们需要知道,++是会改变数值的,也就是++上去的数值,数值是会进行变化的
z = ( (x++) > (y++) ? (x++) : (y++));
x=6 y=10 z=9
宏替换的潜规则
这里还是拿上个例子来进行举例
这里每一次都进行++
这里我们看一下预处理阶段发生的事情
‘M’这里的字符在预处理阶段是不会被搜索到的,哪怕定义了宏M
宏替换的规则
在程序中扩展#define定义符号和宏时,需要涉及⼏个步骤。
1. 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先
被替换。
2. 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上
述处理过程。
注意:
1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。