【保姆级讲解】C语言---预编译处理精华

预编译处理

1.1预编译处理概述

预编译处理也称为编译预处理,是在程序正式编译之前需要进行的前期编译处理阶段。主要作用是向编译器传递信息。以井号(“#”)开头的命令都是编译预处理命令,并且编译预处理命令后面没有分号(“;”)

预处理:头文件 #include <stdio.h>   预处理阶段进行的(完成替换)   后面没有;

预处理阶段相关命令:GNU套件中的gcc编译器 参数-E 生成文件后缀为xxx.i

未包含头文件的预处理与源文件的比较:

编译预处理命令格式:gcc   -E  1.c  -o  1.i

包含头文件的预处理与源文件的比较:

进行替换:

预处理==替换

1.2常用预编译处理命令

  1. 文件包含命令(#include)

#include预编译命令主要用于插入(包含)头文件。使用“#include <头文件名称>”或“#include “头文件名称””的格式来插入(包含)一个具体的头文件。尖括号(<>)和双引号(””)表示头文件的查找路径不同:

  1. <>:在系统指定目录(软件安装目录)下查找需要插入的头文件。

Linux中寻找的为/usr/include/文件夹;

  1. “”:在整个工程目录下查找插入的头文件,如果找不到,再到系统指定目录(软件安装目录)下查找。

情况1:

#include “stdio.h”

如果你的工程目录下有stdio.h则发生替换需要采用工程下stdio.h不再使用标准库下的stdio.h

如果您的工程目录下没有stdio.h则查找标准库下的头文件;

以上编译器首先查找当前工程目录下stdio.h;找到出现错误---没有printf函数;

情况2:

自己编写字符串函数头文件为string.h,即可抛出标准库string.h----头文件格式一定是””;

情况3:

当前目录下没有stdio.h文件,采用#include ”stdio.h”形式,归根到底还是查找标准库中的<stdio.h>;这样做的结果是:编译预处理时间耗时变长;(查找是需要时间的);

以后#include “”与<>要合理;

  1. 宏定义(#define)
  1. 宏定义概述

宏定义就是替换的意思,主要是把表达式、常量等内容,利用一个自定义的标识符号进行替换。

替换意思:位置不变 只替换内容

原:Abcdef:将cd替换为12    结果:Ab12ef

  1. 宏应用
  • 无参宏

无参宏是指这个宏定义不需要参数的输入,仅仅是用于替换。使用“#define A B”的格式来进行无参宏定义。

  1. 替换一个数据类型 -- #define 别名 数据类型

#include <stdio.h>

//a)替换一个数据类型 -- #define 别名 数据类型

#define DATA_INT int //宏定义为大写标识

int main()

{

DATA_INT A = 10;

DATA_INT C =A+13;

printf("%d\n",C);

return 0;

}

gcc -E 1.c -o 1.i预处理阶段会将define宏定义的内容进行替换;

  1. 替换一个表达式

#define A  1+2   //表达式与语句区别 表达式是由运算符结合起来的式子;语句是表达式后面加;

经常犯错的情况:

#include <stdio.h>

//a)替换一个数据类型 -- #define 别名 数据类型

#define DATA_INT int //宏定义为大写标识

#define NUM   1+2

int main()

{

DATA_INT A = 9;

DATA_INT C =A/NUM;//9/1+2    9+2

printf("%d\n",C);

return 0;

}

  • 有参宏

有参宏是指在宏定义中的参数称为形参,在宏调用中的参数称为实参。对带参的宏,在调用的过程中,不仅要宏展开,而且还需要使用实参去代替形参。

  1. 替换一个运算公式

#include <stdio.h>

#define MIN(x)  x

int main()

{

int A =10;

printf("%d\n",MIN(A));

return 0;

}

例如:define M(y)   y+y

#include <stdio.h>

#define M(y)   y+y

int main()

{

int C = M(4)/M(2);  //y+y/y+y   4+4/2+2 8

printf("%d\n",C);

return 0;

}

替换函数

例如:#define LEN(x)   strlen(x)

#include <stdio.h>

#include <string.h>

#define LEN(x)   strlen(x)

int main()

{

printf("%d\n",LEN("hello"));

return 0;

}

宏只是进行替换的,变量是负责在内存中占用时的标识;

如果一个宏定义代替多条语句,建议采用do{}while(0)形式:

#include <stdio.h>

#include <string.h>

//

#define PRINT   do{printf("1111112222\n"); printf("22222233333\n");}while(0)

int main()

{

PRINT;

return 0;

}

1.3条件编译

条件编译是根据实际宏定义(某类条件)进行代码静态编译的手段。可以根据表达式的值或某种特定宏是否被定义来确定编译的条件。

  1. 条件与编译模型1

模型1和模型3一般常用于对操作系统、GUI程序等进行功能裁剪(如果表达式为真,则对这段程序进行编译或有xxx这个定义,则这段程序有效)。

#define 标识符

#ifdef 标识符

  程序段1;

#else

  程序段2;

#endif

运行规律:如果标识符已经被定义,执行程序段1,未定义,执行程序段2。

例:

#include <stdio.h>

#include <string.h>

#define _INIT_

//:如果标识符已经被定义,执行程序段1,未定义,执行程序段2。

int main()

{

#ifdef _INIT_

int A =10;

int B =20;

int C = A+B;

printf("int C = A+B:%d\n",C);

#else

int A =20;

int B =30;

int C =B-A;

printf("int C =B-A:%d\n",C);

#endif

return 0;

}

注意:

int _INIT_;

#define _INIT_

条件编译标识与变量名是不一致的;需要区别;

条件与编译模型2

模型2一般用于防止头文件的重复编译。

#ifndef 标识符

  程序段1;

#else

  程序段2;

#endif

运行规律:如果没有定义标识符,执行程序段1,如果已经定义,执行程序段2。

#include <stdio.h>

#include <string.h>

#define _INIT_

int main()

{

#ifndef _INIT_   //如果没有定义则运行下面表达式  如果定义则运行else

int A =10;

int B =20;

int C = A+B;

printf("int C = A+B:%d\n",C);

#else

int A =20;

int B =30;

int C =B-A;

printf("int C =B-A:%d\n",C);

#endif

return 0;

}

#define与ifdef或者ifndef是有前后顺序要求的;

条件与编译模型3

#if 条件表达式

   程序段1;

#else

   程序段2;

#endif

运行规律:条件表达式为真,编译程序段1,如果为假,编译程序段2

#include <stdio.h>

#include <string.h>

#define _INIT_

#define NUMA 30

#define NUM 20

int main()

{

#if NUMA > NUMB  //1   //0

int A =10;

int B =20;

int C = A+B;

printf("int C = A+B:%d\n",C);

#else

int A =20;

int B =30;

int C =B-A;

printf("int C =B-A:%d\n",C);

#endif

return 0;

}

注:在所有条件预编译中#else可以没有,但#endif(结束条件编译必须存在)。模型1和模型3一般常用于对操作系统、GUI程序等进行功能裁剪(如果表达式为真,在编译这段程序或有xxx这个定义,则这段程序有效)。模型2一般用于防止头文件的重复编译。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

面试僧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值