我在Linux(man gcc
)上的gcc手册中寻找-c
选项(gcc -c infile
)的内容,
-c:编译或汇编源文件,但不链接。链接阶段只是没有完成。最终输出是以每个源文件的目标文件的形式。
默认情况下,源文件的目标文件名是通过将后缀.c,.i,.s等替换为.o来实现的。
此外,在检查ELF文件和目标文件(带有file
指令)时,输出是相同的:
file ./out/main.o: ELF 32-bit LSB relocatable, Atmel AVR 8-bit, version 1 (SYSV), not stripped
file ./out/main.elf: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped
所以它们都有相同的描述。 我的问题是:
-c
选项和一些标志(-Wall -g -std=c99 -Os
)编译了一些源文件并从中获取目标文件,这些标志在ELF文件生成时是否仍然存在(我可以在生成时跳过这些标志吗? ELF文件(如果我在目标文件上使用了它们)? 答案 0 :(得分:1)
让我们举一个简单的例子。您有三个文件:
cnt.h
void inc_counter();
void print_counter();
cnt.c
#include <stdio.h>
#include <cnt.h>
static int counter= 0;
void inc_counter() {
couner++;
}
void print_counter() {
printf("Counter: %d\n", counter);
}
main.c
#include <counter.h>
int main(char** args) {
inc_counter();
print_counter();
return 0;
}
然后,您编译cnt.c
和main.c
以创建cnt.o
和main.o
。
cnt.o
将包含get_counter
和inc_counter
的可执行代码。每一个都有一个入口点。但是代码不是可执行的。 printf
的呼叫将不起作用,因为尚不知道printf
的地址。因此,该文件包含的信息将需要在以后修复。main.o
将包含main
的可执行代码和它的入口。同样,inc_counter
和print_counter
的引用将不起作用。第二步,将链接文件cnt.o
,main.o
和标准C库,并创建可执行输出文件(带有.elf
或不带扩展名)。链接器将在inc_counter
的调用和函数inc_counter
之间创建丢失的链接。它将对print_counter
和printf
进行同样的操作,从而包括来自标准库的printf
的代码。
因此,尽管两种文件类型都主要由可执行代码组成,但是.o
文件仅包含部分代码,而.elf
文件则包含完整的程序。
注意:创建或使用动态链接的库时,还有其他变化。但是为了简单起见,我将它们排除在外。
答案 1 :(得分:0)
.o文件包含一个来源(编译单元)的已编译代码,但尚未准备好运行:它可以包含对库或其他目标文件中外部符号的引用。
那是可执行文件(Windows中的.exe)。它是由链接阶段(由链接器)生成的,该链接阶段搜索库和其他目标文件以解析.o文件中的外部引用。
是的,您需要它们才能链接它们,但它们是中间文件。
某些标志“持久”是指它们确定.o文件,但不是全部。 -Wall
仅在编译期间发出警告,-Os
指定某种优化类型,这将导致.o文件对执行的代码进行某种优化。