[linux学习笔记]02 gcc安装与使用

安装gcc:sudo apt-get install gcc

一. 程序从源代码到可执行目标文件的四个阶段:

  1. -E 预编译 —>.i文件
  2. -S 编译 —>.s文件 内容为汇编语言
  3. -c 汇编 —>.o文件
  4. -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编译器有很多参数,可以对编译过程进行控制,下面介绍一些常用的参数:

  1. -o参数:指定编译后的可执行文件名。
    gcc -o test test.c
    上面的命令会将test.c文件编译成可执行文件test。

  2. -c参数:只编译不链接,生成目标文件。
    gcc -c test.c
    上面的命令会将test.c文件编译成目标文件test.o,但是不进行链接操作

  3. -E参数:只进行预处理,不进行编译。
    gcc -E test.c
    上面的命令会对test.c文件进行预处理,输出预处理结果到屏幕上。

  4. -Wall参数:显示所有警告信息。
    gcc -Wall test.c
    上面的命令会编译test.c文件,并显示所有警告信息。

  5. -g参数:为可执行文件添加调试信息。
    gcc -g test.c
    上面的命令会将test.c文件编译成可执行文件test,并加入调试信息。

  6. gcc -S test.c
    生成a.s文本文件,是一个汇编语言的文件

  7. 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
============================================================
  1. gcc test.c
    直接生成test.out可执行文件
    .o文件与.out文件
    .o文件是由各个单独的源文件经编译后生成的可重定位的目标文件。
    .out文件时可执行目标文件,是由.o文件经过链接后形成的。
  2. 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
  1. 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
  1. gcc a.c -I./ 或者 gcc a.c -I.
    将当前目录添加到标准库目录处,这使得我们可以使用<>包含自己的头文件,而不是""双引号。
    #include

三. C文件与C++文件的链接

如果期望将文件看作C文件而不是C++文件,需要在该函数的声明处添加extern “C”关键字

// foo.c
extern "C" {	// 在函数定义中添加extern "C" 关键字
int foo() {return 10;}
}
// cal.cpp
#include 
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

你可能感兴趣的:(linux,linux学习,linux,学习,笔记)