文章目录

  • #define
  • 1. #define 定义标识符
  • 2. #define 定义宏
  • 3 #define 替换规则
  • 4. #和##
    • 4.1 `#`
    • 4.2 `##`
  • 5. 带有副作用的宏参数
  • 6. 命名规定
  • 7. 宏和函数的区别

#define

C语言中可以使用#define来定义一个标识符来表示一个常量,或定义一些宏 定义的标识符,并不占用程序内存,在预编译阶段对程序代码进行文本替换

1. #define 定义标识符

#define ARR_SIZE 10;

最常见的用法就是#define来定义一些常量.

例:

#include #define ARR_SIZE 10int main(){int arr[ARR_SIZE] = { 0 };int sz = ARR_SIZE;for (size_t i = 0; i < sz; i++){arr[i] = i + 1;printf("%d ", arr[i]);}}


注意:在define定义表示符时,建议不需在最后加上;.
如图:

在预先编译后,编译器会将程序中带要标识符的位置与标识符所表示的信息产生文本替换,若#define所表示的表达式带有;号,则可能出现危险的错误!!!

2. #define 定义宏

#define 不仅仅可以表示常量,也可以表示一些表达式.它可以将参数替换到表达式中,再将表达式替换到程序中,这种行为通常称为宏.

#define MAX(a,b) a>b" />:b 

这是一个三元表达式宏.
其中 (a,b)是一个由逗号隔开的符号表,它则出现在该宏多定义的表达式中
注意: (a,b)的左括号必须紧挨这宏名,若两者中出现空白符号,则参数列表就会被解释为表达式的一部分.

#include #define MAX(a,b) a>b?a:bint main(){int a = 5;int b = 6;printf("%d",MAX(a,b));}


注意:

在使用#define用于表达式求值时,表达式中应该参数应该独属一对括号中,以免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的作用.

如:

#include #define TMP(a,b) a * bint main(){int a = 5;int b = 6;printf("%d",TMP(a + 1,b));}


结果是不是出乎意料” />#define TMP(a,b) (a) * (b)

3 #define 替换规则

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

  1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先
    被替换。
  2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
  3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上
    述处理过程。
    注意:
  4. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
  5. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

4. #和##

4.1 #

#是在#define中可以将参数转换为字符串格式.

#define PRINT(x) printf("hello "#x)

以上宏当传入参数pear,则实际为:printf("hello ""pear")
我们来看看代码:

#include #define PRINTF(x) printf("hello "#x)int main(){PRINTF(pear);}


可以看到在宏中,# 则是将参数转化为"参数" 这种格式.

4.2 ##

在宏中##则是对参数进行拼接.

#define ARR_SUM(num,value) arr##num = value


我们可以使用##配合宏定义即可花式操作变量.

注意:

# 和 ## 只能在#define里才能产生如此效果.

5. 带有副作用的宏参数

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

x + 1;//不带副作用x++//带有副作用

之前的三元表达式宏就可以很好的体现宏的副作用!

#include #define MAX(a,b) (a)>(b)" />(a):(b)int main(){int i = 3;int j = 4;int k = MAX(i++,j++);printf("i=%d j=%d k=%d",i,j,k);}


可以看到再预编译后,int k = (i++)>(j++)" />6. 命名规定

可以看到,宏和函数的使用语法很相似,所以语言无法区别二者
那我们可以养成一个习惯

把宏名全部大写
函数名不要全部大写

7. 宏和函数的区别

宏:

  1. 宏在程序中,会比函数执行速度更快.
  2. 宏没有参数类型检测.而函数行形参必须定义类型.
  3. 若宏代码很长,则会增加编译后代码的长度.

函数:

  1. 再需要进行庞大的计算时,函数创建与销毁所需时间可以忽略不计时,则函数比宏简便
  2. 函数可以调试,但宏不可以
  3. 函数可以递归,宏不可以