我在这篇文章中积累了三个不同但背景相似的问题。以下相同。
- 源代码->可执行的步骤顺序
- 32/64 位版本的编译器
- c 数据类型大小对编译器的依赖性
Q1:从源代码到>可执行
的步骤顺序
我假设以下是从源文件生成可执行文件的步骤
- 编写的源文件是用任何高级/中级语言编写的,经过编译器预处理。
- 当我们使用 GCC/G++ 时,然后 gcc -save-temps -c 生成一个 .S 和一个 .O 文件,它们是程序集(可读)和目标代码(人类不可读)。
- 最后阶段是链接此目标代码以解析未知符号以创建机器(或)可执行代码。
所以这里的问题是这些假设是否正确?我经常看到术语对象和机器代码可以互换使用。两者之间的确切区别是什么?
Q2:32/64 位版本的编译器
在第 1 季度的上述步骤中,编译器类型的影响到底在哪里。是不是生成的汇编代码变了?
问题 3:c 数据类型大小对编译器的依赖性
就 C 编程而言,数据类型的大小是否取决于编译器类型(或)硬件类型。请详细说明这些因素的依赖性。虽然在 stack overflow 看到了一些与 Q3 的讨论,但对此我还是很疑惑。
第一季度
差不多吧,不过可能没有组装阶段。 “预处理”是一个含义丰富的小词。
对象和机器代码通常几乎相同。目标代码可能包含机器代码或一些可解释的代码,非机器代码。目标代码通常不是执行的最终代码,需要链接器进一步处理。包含机器代码的可执行文件通常需要一些类似于链接器的处理,但这部分是由操作系统完成的。可执行文件可重定位是可取的,也就是说,能够将它们加载到内存中的任何位置以在那里运行它们。重定位涉及在可执行文件加载之后但在执行之前修复可执行文件内部的地址。在运行时链接到 DLL 是操作系统执行的另一个类似链接器的功能。
第二季度
“预处理”是类型及其大小开始出现的第一步。编译器必须执行类型检查、类型转换和代码/数据生成。所有这些步骤类型都不能忽略。 0xFFFF 是 int
还是 unsigned int
?编译器应该为指针保留多少内存?应该为 100 个 double
的数组分配多少空间?编译器究竟如何将 chars
提升为 ints
?代码优化呢?所有这些问题的答案都需要知道字号。当然,生成的汇编代码或机器代码将取决于它们。
第三季度
理论上,类型大小取决于编译器。实际上,为了避免模拟目标硬件不直接支持的类型的不必要开销,您拥有的类型直接对应于硬件支持的类型。 C 在其起源和本质上几乎是一个可移植的汇编器,这应该可以解释它的很多“奇怪之处”(太原始,让你很容易搬起石头砸自己的脚,有许多未定义和特定于实现的行为,等等) ).