源代码构建混淆(预处理和链接)

时间:2017-05-21 23:08:57

标签: c++ build linker preprocessor

为什么在预处理步骤中,主文件中的#includes只会替换为相关头文件的内容(而不是函数定义(.cpp文件))?

我认为在这一步中它应首先进入头文件并用其关联的.cpp文件的内容替换#includes然后然后返回以替换主文件中的#includes一切,因此否定了任何链接的需要(一个巨大的文件与一切)。为什么不这样呢?

3 个答案:

答案 0 :(得分:0)

  

为什么在预处理步骤中,主文件中的#includes只会替换为相关头文件的内容(而不是函数定义(.cpp文件))?

简单地说,头文件是你告诉预处理器的唯一文件。它不能假定源文件的名称,因为任何给定标头可能有许多源文件。您可能会想“嘿,为什么我不包含源文件?”而我在这里告诉你 不!不好!<​​/ em> 此外,谁首先说你有权访问源文件?

编译器了解和编译所有源文件的唯一方法是让每个源文件传递编译器,将它们编译成对象,并将这些对象链接到库或可执行文件中。

答案 1 :(得分:0)

compiling and linking

之间存在很大差异

预处理器,预编译时和编译时:

预处理器检查#符号并将其替换为相关内容,例如:

#include <iostream> // the content will be replaced here and this line will be removed

所以iostream的内容将在上面添加。

EG2:

#define PI 3.14 // wherever PI is used in your source file the macro will be expanded replacing each PI with the constant value 3.14 

编译器只检查syntax errors,函数原型... and doesn't care about the body of functions, resulting in an。obj file`。

链接时间:

链接器将这些obj files与相关库链接起来,在这个时间functions called必须有一个定义;没有定义会在链接时错误中发出。

答案 2 :(得分:0)

  

为什么不以这种方式发生?

历史和有经验的程序员的期望,以及他们对更大程序的经验(见下文最后的陈述)

  

我认为在这一步中它应该首先进入标题   文件并将#includes替换为其中的内容   关联的.cpp文件......

如果您接受使用C ++编写的职位,您的公司将向您提供编码标准,详细说明您希望遵循的指导方针或规则,或者在您偏离时保护您的选择。

您现在可能需要一些时间来查看可用的编码标准。例如,尝试研究Google C ++样式指南(我不特别喜欢或不喜欢这个,它很容易记住)。一个简单的谷歌搜索也可以找到几个编码标准。添加“为什么符合编码标准?&#39;您的搜索可能会提供一些信息。

  

否定任何链接的需要(一个巨大的文件包含所有内容)。

注意:此方法无法消除与编译器工具或第三方提供的库的链接。我经常使用-lrt和-pthread,有时使用-lncurses,-lgmp,-lgmpxx等。

目前,作为一项实验,您可以手动实现巨型文件方法(我经常为我的小型试用版和私有工具开发)。

考虑:

如果main.cc有:

#include "./Foo.hh" // << note .hh file

int main(int argc, char* argv[])
{
   Foo  foo(argc, argv);

   foo.show();   
...

和Foo.cc有

#include "./Foo.hh"  // << note .hh file

// Foo implementation

这是常见的模式(不是,不是模式书模式),并且需要你将Foo.o和main链接在一起,这对于小型构建来说是微不足道的,但还有更多事情要做。

&#39;小&#39; -ness允许您使用#include创建一个包含所有内容的巨型文件&#39;容易:

将main更改为

#include "./Foo.cc"   // << note .cc also pulls in  .hh
                      // (prepare for blow back on this idea)    

int main(int argc, char* argv[])
{
   Foo  foo(argc, argv);

   foo.show();   
...

编译器会在一个编译单元中看到所有代码。不需要链接本地.o(但仍然是库链接)。

注意,我不推荐这个。为什么呢?

可能主要原因是我的许多工具都有100个对象(即100个.cc文件)。那个单身巨人&#39;文件可能很大。

对于大多数开发流失(即早期错误修复),只有一个或两个.cc文件得到更改。重新编译所有源代码可能会浪费你的时间和编译器的时间。

另一种选择是开发人员已经学到的经验:

A)编译更少数量的.cc已更改(可能是一两个?),

B)然后将它们与其他没有改变的其他内容联系起来,构建速度要快得多。

提高工作效率的一个关键是最小化编辑 - 编译 - 调试持续时间。 A和B以及一个好的编辑器对于这个开发迭代非常重要。