python define应用_C语言-宏的使用

预处理指令的特点

1,以#开头

2,预处理指令都是在编译之前执行的

预处理指令后面都是没有分号

C 程序从编写到编译,链接,执行的一个流程

1,新建一个.c 源文件,.c 的文件是c 程序的源文件

2,在.c 的源文件中写上符合 c 语法规范的源代码

C语言严格区分大小写

除了字符串常量,其他的地方必须使用英文输入法

3,使用 cc -c 指令去编译源文件

格式:cc -c 源文件名称

编译做的事情

a,先执行源文件中的预处理指令,如果有文件包含指令,就将文件的内容拷贝到指令的地方

b,检查 .c 文件中的语法是否符合规范

1,如果符合,生成.o 目标文件,就是.c 文件对应的二进制指令

2,如果不符合语法规范,就报错,不会生成.o 的目标文件

4,链接

cc xx.o

a,为.o 的目标文件添加启动代码

b,链接函数,告诉编译器要调用的函数在什么地方,调用的时候,去正确的地方找实现

c,链接成功以后,就会生出一个可执行文件,这个文件就是我们程序了

预处理指令的分类

文件包含指令 # include

宏定义:可以将一段 c 代码定义为 1 个标识,使用这个标识就可以使用这段代码

条件编译指令:

宏定义:

他是一个预处理指令,所以他在编译之前执行

作用:

可以为一段 C 代码定义一个标识,如果你要使用这个 c 代码,那么就是用这个标识就可以了

语法:

----#define 宏名 宏值

----#define N 10

如何使用宏

在C 代码中,直接使用宏的名称就可以了

宏的原理是

在预编译的时候,就会执行源文件中的预处理指令,会将 C 代码中使用宏名的地方替换为宏值,

将 C 代码中的宏名替换为宏值的过程就叫做宏替换

在使用宏的时候需要注意的地方

宏值可以是任意的东东(常量,表达式),在定义宏的时候并不会去检查语法,但是替换的时候就会检查语法了

#include

# define M 10

# define N 10+10+10

int main(int argc, const char * argv[]) {

int num = M+10;

printf("M = %i\n",M);

printf("num = %i\n",num);

// 宏值是整个表达式,而并不是计算的结果

int num1 = N * 2;

printf("num1 = %i\n",num1);

return 0;

}

无论宏值是什么东西,在定义宏的时候不会去检查语法,只有当完成了宏替换的时候才会去检查替换以后是否符合语法规范

如果宏值是一个表达式,宏值并不是这个表达式的结果,而是这个表达式的本身

如果宏值中包括一个变量名,那么在使用这个宏之前必须保证这个变量存在不然就会报错

# define X a+a

int main(int argc, const char * argv[]) {

int a = 10;

int num2 = X;

return 0;

}

无法通过赋值符号给宏改值,因为宏根本就不是变量

宏的作用域问题

a, 宏可以定义在函数里面也可以定义在函数外面

b,从定义宏的地方,后面的所有的地方都可以使用这个宏,跟变量不一样,就算这个宏定义在这个大括号里面,在这个后面也是可以访问的

undef 宏名 -->解除宏指令

默认情况下,宏从定义的地方一致到文件结束都可以使用,#undef 宏名可以让指定的宏提前消失

字符串中如果出现了宏名,并不会认为是一个宏,而是认为是字符串的一部分,字符串中并不会出现宏替换

宏的层层替换

宏值当中我们用到了另外一个宏名,那么就会将这个宏值当中的宏名替换为对应的宏值

# define P 3

# define A 5

# define JISUAN P*A

int main(){

printf("JISUAN = %i\n",JISUAN);

}

如果后面跟了分号,那么就会将分号作为宏值的一部分,但是建议不要这么写

C语言的代码都可以用作宏值

# define p printf

# define d "%i"

int main(){

p(d,10);

return 0;

}

define 和 typedef 的区别

----#define 是一个预处理指令,在预编译的时候执行,在预编译的时候会把宏名替换为宏值

typedef 是一个 C 代码.在运行的时候执行

----#define可以将任意的C 代码取 1 个标识名

typedef 只能为数据类型取名字

宏的高级用法

我们在定义宏的时候,宏名是可以带参数的,在这个宏值当中,可以直接使用这个参数

如果使用的宏有参数,那么就必须要在使用它的时候为这个宏的参数传值

# define B(a) a+10+a

int main(){

// 有参数的宏

int num3 = B(8);

printf("num3 = %i\n",num3);

return 0;

}

宏替换的原理是什么?

先将传入的值传递给宏的参数,那么宏的参数的值就是我们传递的值

再把宏值当中使用参数的地方换成参数的值

最后,再将使用宏名的地方,替换为最后的宏值

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

int main(){

printf("最大值是:%i\n",MAX(10, 0));

return 0;

}

使用带参数的宏注意点

宏不是函数,所以宏的参数不需要写数据类型,直接写参数名称即可

我们在定义宏的时候,编译器是如何区分宏名和宏值的呢?

----#define空格宏名空格宏值 --->两个空格之间的就是宏名

为带参数的宏传递的时候是本色传递(本色传递:你给的什么,那就是什么,预编译的时候啥都没有就是直接本色的替换)

宏一定程度上可以实现和函数一样的效果

宏一旦换了行就代表宏定义结束了,

代码很少的时候会使用宏,只有一句,两句的时候可以使用宏

条件编译指令

他也是一个预处理指令,所以在预编译阶段执行

作用:默认情况下我们所有的 C 代码都会被编译为二进制代码,条件编译指令的作用:可以让编译器只编译置顶的部分

条件编译指令的一种用法

if 条件

c 代码

endif

# define M 10

int main(){

// 条件编译指令

#if M == 10

printf("我是条件编译指令的代码\n");

#endif

return 0;

}

// 输出:我是条件编译指令的代码

注意:条件只能是宏,不能是变量,因为:预编译的时候变量还没有呢

int m = 10;

#if m == 10

printf("我是 变量 m == 10 才会执行的代码\n");

#endif

条件编译指令的第二种用法

# define M 10

int main(){

#if M > 0

printf("M>0编译这个代码\n");

#elif M > 0 && M < 20

printf("M > 0 && M < 20编译这个代码\n");

#elif M >20 && M < 40

printf("M >20 && M < 40编译这个代码\n");

#else

printf("否则编译这个代码");

#endif

return 0;

}

条件编译指令和 if 语句的对比

1,条件编译指令是一个预处理指令,在预处理阶段执行,if 语句是 C代码.在程序运行的时候执行

2,if 语句全部都要被编译为二进制指令,条件编译指令只会编译条件符合的代码

3,实际上,if 语句一定程度上可以换成条件编译指令,但是条件编译指令的条件不能是变量参与,只能是宏

条件编译指令的第三种用法,如果定义了指定的宏,就编译指定的代码

#define M 10

int main(){

// 第三种用法

#if M

printf("如果定义了这个宏,就执行这个代码\n");

#endif

return 0;

}

int main(){

// 第三种用法

#ifndef M

printf("如果没有定义了这个宏,就执行这个代码\n");

#endif

return 0;

}

条件编译指令的应用场景

// 在调试的时候,调试信息有很多,又不想每次都一个一个的删除,那么可以使用条件编译指令,每次只需要修改自己定义的宏就可以对 printf 函数的控制

#include

# define SHAN_DEBUG 0

# if SHAN_DEBUG == 0

# define print(val1,val2) printf(val1,val2)

# else

# define print(val1,val2)

# endif

int main(int argc, const char * argv[]) {

print("%d",10);

return 0;

}

// 无论一个文件包被#include 多少次,我只引入一次

#ifndef lianxi_h

#define lianxi_h

#include

// 写自己的代码

#endif /* lianxi_h */

// 原理:在 main.c中#include lianxi.h,导入很多次,#include 的作用就是将此文件全部复制过来,所以复制第一次在编译的时候如果没有导入 lianxi.h 这个文件,全部被copy 过来,此时没有定义 lianxi.h 这个宏,那么就定义这个宏 lianxi.h,然后在第二次copy 过来的时候,发现定义了这个 lianxi.h 这个宏,所以就不会重复的 copy 了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值