安装gcc:sudo apt-get install gcc
一. 程序从源代码到可执行目标文件的四个阶段:
- -E 预编译 —>.i文件
- -S 编译 —>.s文件 内容为汇编语言
- -c 汇编 —>.o文件
- -static 链接 —>.out文件
foo.c文件
int foo()
{
int sum {};
for (int i {};i < 10; i++)
sum += i;
return sum;
}
b.c文件
int foo(); // 函数声明
int main()
{
printf("sum = %d",sum);
}
#进行编译,每个源文件单独编译,形成.o可重定位目标文件,a.o及b.o
gcc -c foo.c
gcc -c b.c
#b.c中调用了a.c中的函数,因此两个.o目标文件需要经过链接
gcc foo.o b.o -static #默认生成a.out,想要生成指定名称的.out文件
gcc foo.o b.o -static -o cal.out
二. GCC编译器有很多参数,可以对编译过程进行控制,下面介绍一些常用的参数:
-
-o参数:指定编译后的可执行文件名。
gcc -o test test.c
上面的命令会将test.c文件编译成可执行文件test。 -
-c参数:只编译不链接,生成目标文件。
gcc -c test.c
上面的命令会将test.c文件编译成目标文件test.o,但是不进行链接操作。 -
-E参数:只进行预处理,不进行编译。
gcc -E test.c
上面的命令会对test.c文件进行预处理,输出预处理结果到屏幕上。 -
-Wall参数:显示所有警告信息。
gcc -Wall test.c
上面的命令会编译test.c文件,并显示所有警告信息。 -
-g参数:为可执行文件添加调试信息。
gcc -g test.c
上面的命令会将test.c文件编译成可执行文件test,并加入调试信息。 -
gcc -S test.c
生成a.s文本文件,是一个汇编语言的文件 -
objdump -d test.o
可对二进制文件进行反汇编
// a.c
int main(){}
// 使用gcc对a.c进行编译
gcc -c a.c // 默认生成a.o文件
// 使用objdump进行反汇编
objdump -d a.o
=====================输出结果如下============================
a.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: b8 00 00 00 00 mov $0x0,%eax
d: 5d pop %rbp
e: c3 ret
============================================================
- gcc test.c
直接生成test.out可执行文件
.o文件与.out文件:
.o文件是由各个单独的源文件经编译后生成的可重定位的目标文件。
.out文件时可执行目标文件,是由.o文件经过链接后形成的。 - gcc test.c --verbose
如果没有–verbose选项,我们看不到gcc命令的执行过程。加入verbose选项后,可以得到编译过程中命令执行的具体过程`
gcc a.c --verbose
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
- gcc -m32 test.c
指定gcc编译一个32位的文件(默认为64位),可通过file test.out查看
报错,需要安装支持32位gcc操作系统支持包
lynn@Lynn:~$ gcc -m32 a.c
In file included from a.c:1:
/usr/include/stdio.h:27:10: fatal error: bits/libc-header-start.h: No such file or directory
27 | #include <bits/libc-header-start.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
sudo apt-get install libc6-dev-i386 安装即可
file a.out
a.out: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=5de634f9888570957ea78319d4b647b1f120899c, for GNU/Linux 3.2.0, not stripped
- gcc a.c -I./ 或者 gcc a.c -I.
将当前目录添加到标准库目录处,这使得我们可以使用<>包含自己的头文件,而不是""双引号。
#include <myClass.h>
三. C文件与C++文件的链接
如果期望将文件看作C文件而不是C++文件,需要在该函数的声明处添加extern “C”关键字
// foo.c
extern "C" { // 在函数定义中添加extern "C" 关键字
int foo() {return 10;}
}
// cal.cpp
#include <iostream>
extern "C" {int foo();} // 在函数声明中亦需要添加extern "C" 关键字
int main()
{
std::cout << "Sum= " << foo() << std::endl;
#声明为extern "C" 的C文件在编译后使用的函数名不变,而C++的函数名为编译器指定(考虑到模板的不同函数示例拥有相同的函数名但有不同的函数签名)
g++ -c cal.cpp
g++ -c foo.c
objdump -d foo.o
g++ foo.o cal.o -static -o cal.out
==========================================================
foo.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <foo>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
f: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
16: eb 0a jmp 22 <foo+0x22>
18: 8b 45 fc mov -0x4(%rbp),%eax
1b: 01 45 f8 add %eax,-0x8(%rbp)
1e: 83 45 fc 01 addl $0x1,-0x4(%rbp)
22: 83 7d fc 09 cmpl $0x9,-0x4(%rbp)
26: 7e f0 jle 18 <foo+0x18>
28: 8b 45 f8 mov -0x8(%rbp),%eax
2b: 5d pop %rbp
2c: c3 ret