编译和链接详解-预处理
转自:旧友与酒
-
预处理命令是在编译之前对源代码进行预处理的指令,它们通常以井号(#)开头。这些命令对源代码进行各种处理,如宏定义、文件包含、条件编译等。以下是一些常用的预处理命令:
-
宏定义
#define、条件编译#if,#ifdef,#ifndef,#else,#elif,#endif、宏展开#undef、字符串化#、连接## -
文件包含 (
#include):用于将另一个文件的内容包含到当前文件中。 -
警告指令 (
#warning):编译时产生警告信息(语法形式:#warning message)。 -
错误指令 (
#error):编译时产生错误信息(语法:#error标记-字符串,此指令发出的错误消息包含 token-string 参数。token-string 参数不受宏扩展的约束。此指令在预处理过程中最有用,用于通知开发人员程序不一致或违反约束。)。 -
行控制 (
#line):更改行号和文件名。(语法:#line digit-sequence ["filename"],预处理器将编译器的行号和文件名报告值设置为给定行号和文件名。编译器使用行号和可选文件名来引用它在编译过程中找到的错误。行号通常引用当前输入行,文件名引用当前输入文件。各行在经过处理后,行号将递增。)#include "stdio.h"
int main(void){
printf("-- %s: %d -- \n", __FILE__, __LINE__);
#line 201 "main.c"
printf("-- %s: %d -- \n", __FILE__, __LINE__);
#line 101 "main.c"
printf("-- %s: %d -- \n", __FILE__, __LINE__);
printf("-- %s: %d -- \n", __FILE__, __LINE__);
#line 110 "main.c"
printf("-- ------------\n");
printf("-- %s: %d -- \n", __FILE__, __LINE__);
return 0;
}
-
版本控制 (
#pragma):编译器特定的指令,用于控制编译器行为。具体指令可以参考:Pragma 指令与 __pragma 和 _Pragma 关键字 | Microsoft Learn; -
这些预处理命令在C语言中非常重要,它们允许程序员在编译阶段进行代码的定制和条件编译,从而提高代码的可读性、可维护性和灵活性。然而,不同的编译器可能会提供一些特定的、非标准的预处理指令或对标准指令提供扩展。

- 预处理作为编译过程的第一个阶段,它主要完成以下内容:删除注释、宏展开、文件包含(如果包含的是系统头文件(尖括号
<>),预处理器会在标准系统目录中搜索;如果是本地头文件(双引号""),则在用户指定的目录中搜索。)、条件编译、行控制、错误和警告(以便编译时产生调试用的行号及编译错误警告行号。)、字符串化、标记粘贴等。总的来说,预处理就是对预处理指令的一个处理过程。 - 完成以上操作后会输出预处理后文件:预处理的结果通常生成一个 .i 文件,这个文件包含了原始源代码经过上述步骤处理后的内容。不过,这个文件不是必须的,因为编译器可以直接将预处理的结果传递给编译阶段。编译器将开始实际的编译过程,将源代码转换成机器代码或中间表示形式。