4
|
isomorphismes Marcin · 技术社区 · 14 年前 |
1
9
你有两个选择(取决于你想做什么)。要么你一次给编译器所有的源文件,这样它就有了所有的定义。
或者,你用
这将产生
编辑:包含和链接有什么区别?
预处理
包含的目的是使声明可见。为了使用函数
编译 这是编译器运行并将源代码转换为机器代码的部分。请注意,机器代码与 可执行文件 代码。可执行文件需要有关如何将机器代码和数据加载到内存中,以及如何在必要时引入外部动态库的附加信息。这不是在这里做的。这只是代码从C++到原始机器指令的部分。
与java、python和其他一些语言不同,C++没有“模块”的概念。相反,C++是以
翻译单位
. 在几乎所有情况下,翻译单元都对应于单个(非头)源代码文件,例如。
编译源文件时,先运行预处理器,然后执行
编译转换单元时,必须对使用的每个函数和每个变量
宣布
. 编译器将不允许您调用没有声明的函数或使用没有声明的全局变量,因为这样它就不知道所涉及的类型、参数、返回值等,并且无法生成合理的代码。这就是您需要头文件的原因——请记住,此时编译器甚至不知道是否存在任何其他源文件;它只考虑处理
在编译器生成的机器代码中,没有变量名或函数名之类的东西。一切都必须成为一个内存地址。每个全局变量都必须转换为存储它的内存地址,每个函数都必须有一个内存地址,执行流在调用它时会跳转到这个地址。对于那些 定义 (即对于功能, 实施 )在翻译单元中,编译器可以分配一个地址。对于那些 宣布 (通常是包含头的结果)并且没有定义,此时编译器不知道内存地址应该是什么。这些函数和全局变量的编译器只有一个声明,而没有定义/实现 外部符号 ,并假定它们存在于不同的翻译单位中。目前,它们的内存地址用占位符表示。
例如,编译
编译翻译单元的结果是
对象文件
(与
决定 外部符号。也就是说,链接器查看一组对象文件,查看它们的外部符号是什么,然后尝试找出应该分配给它们的内存地址,替换占位符。
在你的情况下函数
如果链接器找不到
最后,一旦编译器解析了所有的外部符号,它就会合并所有现在没有占位符的对象代码,添加操作系统需要的所有加载信息,并生成一个可执行文件。塔达!
注意,通过所有这些,文件名一点都不重要。它是一个
那个
... 哇,太长了。 |
2
5
尝试
如果要单独编译,则需要生成对象文件:
|
Daniel Viaño · 将函数移动到不同的文件 7 年前 |
Trojax · 编译多个。c和。h文件 7 年前 |
Stevoisiak · 为什么#包含打破全局变量? 7 年前 |
jaxonjma · 在另一个JSP中动态发送并包含JSP 7 年前 |