编译和链接【二】
文章目录
- 编译和链接【二】
- 前言
- 预处理过程
编译和链接【二】
前言
在我大一的时候, 我使用VC6.0对C语言程序进行编译链接和运行 , 然后我接触了VS, VS code等众多IDE, 这些IDE界面友好, 使用方便, 例如我最喜欢的VS,一键编译运行。对于大一的我,不需要了解编译的整个过程就可以运行,这无疑是非常棒的,并且增加了我对编程的兴趣,同时也简化了我后续的软件开发, 我只需要关心业务和功能代码即可。
但是今天, 我不想“逃课了”,欢迎来到我的频道,本系列 将会介绍编译中的一系列细节。
在正式开始之前,我要推荐两本书,一本是《程序员的自我修养》,另一本是《鲸书》,这两本书对编译的整个过程做了非常详细,非常完备的介绍,但是恰恰如此,我想很多时候,很多知识在工作上是用不到的,也许这句话在很多年多的我会反驳,但是站在工作一年的现在,我将会给你介绍,我所了解的编译和链接。
预处理过程
为了在编译期(这在C++中是一个非常重要的概念),编译期会提供一些预处理命令,使用**#**作为标识,例如:
- 头文件包含:#include, 实现模块化编程
- 宏定义:#define,用于定义常量,提高代码可读性
- 条件编译:#if #else #endif 功能非常强大,例如,可以区分相同架构的不同项目或者区分不同平台
- 编译控制:#pragma 指示编译期完成一些动作
编译期提供的预处理命令,大大方便了程序编写,例如,
想在编译信息的输出窗口打印文本信息:#pragma message(“hello”)
改变编译期的警告信息:#pragma warning
防止多次编译:#pragma once
在整个预处理的过程中,先处理翻译单元的各种预处理命令。编译期是不认识预处理指令的,所以需要在编译期之前进行预处理,而整个预处理包含以下步骤
- 头文件展开
- 宏展开
- 条件编译
- 删除注释
- 添加行号和文件名标识
- 保留#pragma命令
下面我们以一个简单的程序来看看处理完的结果,使用命令:g++ main.cpp -E
/*
* Author: NemaleSu
* Date: 2025/02/10
*/
#include <iostream>
#include <string>
using namespace std;
#define MESSAGE "hello world!"
int main()
{
cout << "hello" << endl;
string str = "world!";
cout << str << endl;
# ifdef MESSAGE
cout << MESSAGE << endl;
# else
cout << "MESSAGE is not defined" << endl;
# endif
return 0;
}
预处理之后:
当然,还有一些其他信息,但是无足轻重,所以就不展示了。
通过预处理前后源文件的变化对比,我们可以看到:当预处理器 遇到#include命令时,会直接将包含的头文件内容展开,并删除# include;当遇到#define宏时,执行同样的操作。当遇到条件编译指 令时,会根据开发者定义的宏标记,选择要参与编译的代码部分,其余部分删除,经过预处理后,#pragma保留,指示编译器在后续的编 译阶段执行一些特定的操作。继续编译预处理后的C程序,在编译信息提示窗口里,我们会看到自己添加的编译提示信息。
关注我,下期将详细介绍程序的编译过程