C语言 - 面试常被问到的预处理

1.由源码到可执行程序的过程

源码.c->(预处理)->预处理过的.i源文件->(编译)->汇编文件.S->(汇编)->目标文件.o->(链接)->elf可执行程序

-> 预处理用预处理器,编译用编译器,汇编用汇编器,链接用链接器,这几个工具再加上其他一些额外的会用到的可用工具,合起来叫编译工具链。gcc就是一个编译工具链。

2.预处理的意义

-> 预处理器帮编译器做一些编译前的杂事.

-> 编译器本身的主要目的是编译源代码,将C的源代码转化成.S的汇编代码。编译器聚焦核心功能后,就剥离出了一些非核心的功能到预处理器去了。

3.编程中常见的预处理

-> #include 头文件原地展开。

-> 注释,会把所以注释去掉。

-> #if #elif #endif #ifdef,选择需要的。

-> 宏定义,替换掉。

4.gcc中只预处理不编译的方法

gcc -E xx.c -o xx.i可以实现只预处理不编译,一般情况下没必要只预处理不编译。

gcc xx.c -o xx可以指定可执行程序的名称。

gcc xx.c -c -o xx.o可以指定只编译不连接,也可以生成.o的目标文件

preprocess.c源代码文件, 通过执行gcc -E preprocess.c -o preprocess.i (只预处理不编译)得到preprocess.i.

#define pchar char *
typedef char * PCHAR

int main(void)
{
	pchar p3,P4;
	PCHAR p1, p2;
	
	return 0;
}
typedef char * PCHAR

int main(void)
{
	char *  p3,P4;
	char *  p1, char * p2;
	
	return 0;
}

总结:宏定义被预处理时的现象有:第一,宏定义语句本身不见了;第二,typedef重命名语言还在,说明它和宏定义是有本质区别的(说明typedef是由编译器来处理而不是预处理器处理的);

5.头文件包含

-> #include <>和 #include" "的区别:<>专门用来包含系统提供的头文件""用来包含自己写的头文件; 

-> <>的话C语言编译器只会到系统指定目录(编译器中配置的或者操作系统配置的寻找目录,譬如在ubuntu中是/usr/include目录来查找头文件。

-> ""包含的头文件,编译器默认会先在当前目录下寻找相应的头文件,如果没找到然后再到系统指定目录去寻找。

-> 头文件包含的真实含义就是:在#include<xx.h>的那一行,将xx.h这个头文件的内容原地展开替换这一行#include语句。过程在预处理中进行。

6.注释

-> 注释是给人看的,不是给编译器看的。

-> 编译器既然不看注释,那么编译时最好没有注释的。实际上在预处理阶段,预处理器会拿掉程序中所有的注释语句,到了编译器编译阶段程序中其实已经没有注释了。

注意:

-> 注释格式尽量统一,建议使用/**/。Linux内核中的注释几乎都使用这个。

-> 边写代码边注释,更改代码的同时更改注释,保证注释与代码一致。

-> 注释和代码同缩进,并且注释与上方代码之间要空出一行。

7.条件编译

有时候我们希望程序有多种配置,我们在源代码编写时写好了各种配置的代码,然后给个配置开关,在源代码级别去修改配置开关来让程序编译出不同的效果,条件编译中用的两种条件判定方法分别是#ifdef 和 #if。

int a = 0;
	#ifdef NUM		// 如果前面有定义NUM这个符号,成立
	a = 111;
	printf("#ifdef NUM.\n");
	#else			// 如果前面没有定义NUM这个符号,则执行下面的语句
	a = 222;
	printf("#elif.\n");
	#endif
	
	printf("a = %d.\n", a);
int a = 0;
	#if (NUM == 0)		// 如果前面有定义NUM这个符号,成立
	a = 111;
	printf("#ifdef NUM.\n");
	#else			// 如果前面没有定义NUM这个符号,则执行下面的语句
	a = 222;
	printf("#elif.\n");
	#endif

区别#ifdef XXX判定条件成立与否时主要是看XXX这个符号在本语句之前有没有被定义,只要定义了这个符号就是成立的。
#if的格式是:#if (条件表达式),它的判定标准是()中的表达式是否为true还是flase,跟C中的if语句有点像。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嵌入式_笔记

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

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

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

打赏作者

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

抵扣说明:

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

余额充值