当前位置:首页 > 技术文章 > 正文内容

C 语言的编译:预处理(c语言预处理功能)

C 语言的编译过程通常分为几个主要阶段,预处理 (Preprocessing) 是其中的 第一个阶段,在真正的编译(将代码翻译成汇编或机器码)开始之前进行。

预处理阶段由 预处理器 (Preprocessor) 执行,它会根据源代码中以 # 开头的 预处理指令 (Preprocessor Directives) 来修改、准备 C 源代码文本。可以将其理解为一个智能的文本替换和处理工具。

预处理主要做了以下几件事情:

* 处理 #include 指令 - 包含头文件 (Header File Inclusion):

* 预处理器会找到 #include 指令所指定的文件(例如 <stdio.h> 或 "my_header.h"),并将其完整内容 替换掉 #include 这一行。

* 这使得你可以在多个源文件中共享函数声明、宏定义、类型定义等。

* 使用尖括号 <...> 通常表示在系统标准的包含路径中查找文件。

* 使用双引号 "..." 通常表示先在当前源文件目录下查找,如果找不到再到系统标准路径查找。

* 处理 #define 指令 - 宏展开 (Macro Expansion):

* #define 用于定义宏。宏分为两种:

* 对象式宏 (Object-like Macro): 简单的文本替换。例如 #define PI 3.14159,预处理器会把后面代码中所有独立的 PI 替换为 3.14159。

* 函数式宏 (Function-like Macro): 带参数的宏,看起来像函数调用。例如 #define SQUARE(x) ((x)*(x))。当你写 SQUARE(a + b) 时,预处理器会将其替换为 ((a + b)*(a + b))。

* 注意: 宏展开是纯粹的文本替换,非常容易出错。例如,在定义函数式宏时,给参数和整个表达式加上括号 () 是非常重要的,以避免运算符优先级问题。同时也要注意宏参数的副作用(如 SQUARE(i++) 会导致 i 被增加两次)。

* #undef 指令则用于取消一个已定义的宏。

* 处理条件编译指令 (Conditional Compilation):

* 这些指令允许你根据预处理时就能确定的条件,选择性地包含或排除某些代码段。这对于编写跨平台代码或包含调试代码非常有用。

* #if, #elif, #else, #endif: 基于常量表达式的值来决定包含哪些代码。

#define VERSION 2

#if VERSION == 1

// 版本 1 的代码

#elif VERSION == 2

// 版本 2 的代码

#else

// 其他版本的代码

#endif


* #ifdef, #ifndef: 检查某个宏是否已被定义 (ifdef) 或未被定义 (ifndef)。

* #ifndef 常用于 头文件保护 (Header Guards),防止同一个头文件被重复包含导致重定义错误:

#ifndef MY_HEADER_H

#define MY_HEADER_H

// 头文件内容...

#endif // MY_HEADER_H


* defined() 运算符: 可以在 #if 或 #elif 中使用,检查宏是否已定义,比 #ifdef 更灵活。

* 移除注释 (Comment Removal):

* 所有的 C 语言注释(包括 /* ... */ 块注释和 // ... 行注释)都会被预处理器移除(通常被替换为空格)。

* 处理其他指令:

* #line: 修改编译器在报告错误或警告时显示的行号和文件名。

* #error: 让预处理器输出一条错误信息并停止编译过程。

* #pragma: 提供了一种向编译器传递特定指令或信息的方式,其行为是编译器实现相关的(例如,用于控制优化、结构体对齐等)。

预处理的结果是什么?

预处理器处理完所有指令后,会生成一个临时的、经过修改和扩展的 C 源代码文件(有时被称为“翻译单元” - Translation Unit)。这个文件不再包含预处理指令和注释,所有的 #include 都被替换为文件内容,所有的宏都被展开。这个“纯净”的 C 代码文件才是真正被传递给下一阶段——编译器 (Compiler)——进行语法分析、语义分析并最终生成汇编代码的输入。

你可以通过特定的编译器选项来查看预处理后的输出,例如:

* GCC/Clang: gcc -E source.c -o preprocessed.c 或 clang -E source.c -o preprocessed.c

总结:

C 语言的编译预处理阶段是一个强大的文本处理步骤,它在正式编译前根据 # 开头的指令(如 #include, #define, #if 等)对源代码进行包含文件、宏展开、条件编译和移除注释等操作,最终生成一个供编译器使用的、经过整理的源代码文件。

扫描二维码推送至手机访问。

版权声明:本文由AR编程网发布,如需转载请注明出处。

本文链接:http://www.arlanguage.com/post/4268.html

分享给朋友:

“C 语言的编译:预处理(c语言预处理功能)” 的相关文章

如何在 CentOS 8 上安装 Nginx centos8.0安装教程

如何在 CentOS 8 上安装 NginxNginx发音为“ engine x”,是一种开源的高性能HTTP和反向代理服务器,负责处理Internet上一些最大站点的负载。它可用作HTTP和非HTTP服务器的独立Web服务器,负载平衡器,内容缓存和反向代理。与Apache[1]相比,Nginx可以...

服务器排障nginx 499 错误地解决

问题描述:近期平台对外开放了数据查询接口,在数据量特别大时,返回结果时间可能会超过3秒,接口开放后,系统本身调用没有问题,其他第三方平台接入时,总会报链接超时问题;问题原因:查看tomcat日志无任何错误,一开始以为是tomcat接收参数最大限制问题,对tomcat做了一次整体优化,修改连接数、修改...

nginx检查提示“unknown directive &quot;stream&quot; in /etc/*/nginx.conf”

yum安装nginx检查时提示“unknown directive "stream" in /etc/nginx/nginx.conf”yum安装nginx,在配置反代时,出现错误:nginx -tnginx: [emerg] unknown directive "strea...

Nginx安装、启动、停止、重载、查看

Nginx介绍Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在开源BSD-like 协议下发行。特点是占有内存少,并发能力强。1、安装 Nginx程序yum install nginx -y 或 dnf install nginx -y2、n...

Nginx实战-监控nginx.conf配置文件,配置文件修改自动重启nginx

1.1 实现目标在学习或者进行nginx测试的时候,耗费在 nginx -s reload/stop 上的命令时间很多,修改任意内容都需要重新启动或者停止启动,基本上状态就是在下面5个状态间来回切换vim nginx.conf修改nginx.conf保存nginx.conf重启nginx刷新浏览器....

http——使用Nginx部署HTTPS服务

https 服务部署使用 HTTPS 需要生成私钥与公钥;某个文件夹中打开 git bash 输入命令:openssl req -x509 -newkey rsa:2048 -nodes -sha256 -keyout localhost-privkey.pem -out localhost-cer...