黑马程序员-----C语言学习之预处理指令

本文深入探讨了C语言预处理指令,包括宏定义、文件包含、条件编译等内容,详细解释了各指令的用法及注意事项,帮助开发者更好地理解和应用预处理功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

预处理指令简介

1.预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理有:宏定义、文件包含,条件编译。

2.了区分预处理指令和一般的C语句,所有预处理指令都以符号"#"开头,并且结尾不用分号

3.预处理指令可以出现在程序的任何位置,它的作用范围是从它出现的位置到文件尾。习惯上我们尽可能将预处理指令写在源程序开头,这种情况下,它的作用范围就是整个源程序文件。

4.预处理指令的格式如下:

#<stadioh>  

#define M 34

#if

#endif

5.在宏定义语名后没有";"

6.C语言提供的预处理指令主要有:宏定义、文件包含、条件编译.

宏定义

A.不带参数的宏定义

1.一般形式
#define 宏名 字符串
比如#define ABC 10
2.作用
由#define指令定义后, 在程序中每次遇到该宏替换名时就用所定义的字符串(或数值)代替它。
例如:
#define TRUE 1
#define FALSE 0
一旦在源程序中使用了TRUE和FALSE, 编译时会自动的用1和0代替。
#define R 10
 int main ()
 {
     char *s = "Radio";
     return 0;
 }
这里所有的R都会被10代替。在编译预处理用字符串替换宏名时,不作语法检查,只是简单的字符串替换。只有在编译的时候才对已经展开宏名的源程序进行语法检查。
3.使用注意
宏名一般用大写字母,以便与变量名区别开来,但用小写也没有语法错误;
被引号包含的内容不会被替换,因为它是字符串;
编译器在处理宏定义时,只是简单的替换,不进行语法检查与运算;
宏的作用范围为,从定位的位置开始到文件结束,也可以通过#undef来提前结束;
宏可以嵌套定义,比如:
#define R  3.0
#define PI 3.14
#define L  2*PI*R
#define S  PI*R*R

B.带参数的宏定义

1.一般形式
#define 宏名(参数列表) 字符串
2.作用
在编译预处理时,将源程序中所有宏名替换成字符串,并且将 字符串中的参数 用 宏名右边参数列表 中的参数替换。
#include 
 
 #define average(a, b) (a+b)/2
 
 int main ()
 {
     int a = average(10, 4);
     
     printf("平均值:%d", a);
     return 0;
 }
如上所示,int a=average(10,4)实际上可以理解为 int a=(10+4)/2=7;

3.使用注意
宏名和参数之间不能有空格,否则会将后面的所有内容当做被替换的内容,比如
#define average (x,y) (x+y)/2
如果条件1成立,那么code1则会在编译的时候编译进去,否则如果条件2成立,则把code2的内容编译进去,和if-else的判断类似,但是本质完全不一样,如果条件1不成立的话,code1根本不会出现在编译后的.o文件中,但if-else的条件不管成立是否,都会被编译进去。

3.注意

#if 一定要和#endif成对使用,否则会将整个文件的后面部分都当做编译的内容(code1),从而导致整个程序不完整。
条件1应该为宏定义,因为预处理指令实在编译之前执行的,在编译之前,变量还未产生,所以应该把宏定义内容当条件。
例如:
那么结果就变成了int a = (a, b) (a+b)/2(10, 4);编辑会报错
带参数的宏在替换时,只是进行简单的替换操作,没有计算,所以为了防止意外,应在每个结果和参数上都添加(),例如
#define average(a,b) a+b
int main()
{
//希望得到的时3+2的结果再乘以2+3的结果
    int b=average(3,2)*average(2,3);
//实际结果为int b=3+2*2+3=10
}

C.宏定义与函数的区别

1.宏定义不涉及存储空间的分配、参数类型匹配、参数传递、返回值问题;
2.函数调用在程序运行时执行,而宏替换只在编译预处理阶段进行。所以带参数的宏比函数具有更高的执行效率。

条件编译

1.概念

在很多情况下,我们希望程序的其中一部分代码只有在满足一定条件时才进行编译,否则不参与编译(只有参与编译的代码最终才能被执行),这就是条件编译。

2.一般形式

#if 条件1
  ...code1...
 #elif 条件2
  ...code2...
 #else
  ...code3...
 #endif
如果条件1成立,那么code1则会在编译的时候编译进去,否则如果条件2成立,则把code2的内容编译进去,和if-else的判断类似,但是本质完全不一样,如果条件1不成立的话,code1根本不会出现在编译后的.o文件中,但if-else的条件不管成立是否,都会被编译进去。

3.注意

#if 一定要和#endif成对使用,否则会将整个文件的后面部分都当做编译的内容(code1),从而导致整个程序不完整。
条件1应该为宏定义,因为预处理指令实在编译之前执行的,在编译之前,变量还未产生,所以应该把宏定义内容当条件。
例如:
#include 
#define isCoded 10
int main()
{
    #if isCoded ==10
    printf("---------");
    #endif
    return 0;
}

4.其他用法

#if define() 的用法与#ifdef()相同。判断是否定义过某个宏,如果定义则执行代码段,比如:
#include 

int main()
{
  #define isDifined
   //如果定义了isDefined这个宏,则编译第一句,否则编译第二句
   #ifdef(isDifined)
   printf("应经定义了isDifined");
 #else
  printf("not define.");
   #endif
}
对应的为#if !define() 和 #ifndef(),其用法和上面相同。

3.文件包含

1.作用

文件包含的作用就是将文件的内容拷贝的代码处。

2.一般形式

A.第一种形式
#include <.....>
作用:直接到C语言库函数头文件所在的目录中寻找文件。
B.第二种形式
#include "文件名"
作用 :系统会先在源程序当前目录下寻找,若找不到,再到操作系统的path路径中查找,最后才到C语言库函数头文件所在目录中查找。

3.使用注意

A.允许嵌套包含,比如a.h包含b.h,b.h包含c.h;
B.不允许循环包含,比如a.h包含b.h,b.h又包含a.h;

C.使用#include不能解决重复包含的情况,会使编译效率降低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值