C语言入门10 编译、include、宏

一、C语言编译过程

  1. 预编译:将.c文件的头文件展开、宏展开,生成.i文件。.i文件仍然是c语言代码,区别只是头文件、宏的源码替代了引用头文件或宏的代码,使程序完整。
  2. 编译:将预处理后的.i文件生成.s汇编文件。.s文件是汇编语言的文件。
  3. 汇编:将.s汇编文件生成.o目标文件。.o是二进制文件。
  4. 链接:将.o文件链接成目标文件

二、include

  • include<>用尖括号包含头文件,在系统指定路径下找头文件。
  • include"" 用双引号包含头文件,先在当前目录下找,如果找不到再到系统指定的路径下去找。

注意:

  • include不仅可以包含.h还可以包含.c,但是一般不建议这么做,因为如果一个.c被包含多次,在预编译阶段就会被展开多次,会导致函数重复定义而报错。
  • 预编译只是对include等预处理操作进行处理并不会进行语法检查,所以即使有错误也不会报错,只有到编译阶段才会进行语法检查

三、定义宏-define关键字

宏:在预编译时候出现会对宏出现的地方进行替换。宏的好处是只修改宏定义,其他地方预编译就会自动重新替换了。
注意:

  • 宏后边不能跟分号
  • 宏的名称尽量用大写,跟变量区分开。
  • 宏定义的作用:从定义的行开始到本文件末尾(如果没有被#undef终止)。
  • 宏可以在任何地方开始定义,不非要是文件头。
  • 宏的名和形参都没有类型

终止宏的定义范围:#undef PI

宏的定义:

  • 不带参宏:#define PI 3.14
  • 带参宏(看起来跟函数有点类似,但本质完全不是一个东西):
    • 定义:#define S(a,b) a*b
    • 使用:printf("S(a,b) = %d\n", S(2, 3));//替换成 2 * 3,也可以嵌套使用:printf("S(a,b) = %d\n", S(S(2, 3),3));

拓展:
那么问题来了,如果宏的定义是#define S(a,b) a*b,但是使用的时候这样写:printf("S(a,b) = %d\n", S(2+3, 3));,最后结果到底是什么呢?
运行结果
可以看到运行结果是11,也就是2+3*3,这里很明确了,宏只会进行单纯的替换,并不会做其他任何操作,包括加个括号之类的,所以使用宏时要考虑清楚。
再把代码换成printf("S(a,b) = %d\n", S((2+3), 3));,这里我们手动添加了一个括号:
运行结果
这样结果就正确了。

四、选择性编译

  • #ifdef:如果宏AAA被定义,就编译代码段一,否则编译代码段二,下面代码编译的是代码段一。
#include<stdio.h>
#define AAA 1.14
int main() {
	#ifdef AAA
		//代码段一
		printf("hello world\n");
	#else
		//代码段二
		printf("hello China\n");
	#endif 
	return 0;
}
  • #ifndef:跟上面#ifdef的作用相反,这里不演示了。注意,不管是从来没有定义过,或者是被#undef终止过的宏,都满足#ifndef的条件。一般用来防止头文件重复包含。

那么,如何防止头文件重复包含呢?我们一般在被包含的文件,也就是.h文件中使用#ifndef,例如:

#ifndef __TEST_H__
#define __TEST_H__
extern int fun();
#endif

这样写即可解决问题,如果在一个.c文件中,test.h被包含两次,那么第二次则不会满足#ifndef __TEST_H__这个条件,因为在第一次中#define __TEST_H__宏已经被定义了。

  • #if [] .... #else ....
    最普通的选择性编译语句,一般通过一个宏作为开关来控制一些语句的编译:
#include<stdio.h>
#define AAA 0
int main() {
	#if AAA
	printf("hello world");
	#endif
	return 0;
}

这样通过控制宏AAA的值,来控制编译是否进行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值