Linux系统编程(一)

写在前面

本文主要介绍Linuxgcc编译的知识

gcc

gcc介绍

gcc最开始的时候是 GNU C Compiler, 如你所知,就是一个c编译器。但是后来因为这个项目里边集成了更多其他不同语言的编译器,所以表示一堆编译器的合集。 g++则是GCCc++编译器。
现在你在编译代码时调用的gcc,已经不是当初那个c语言编译器了。更确切的说他是一个驱动程序,根据代码的后缀名来判断调用c编译器还是c++编译器 g++。比如你的代码后缀是.c,他会调用c编译器还有linker去链接clibrary。如果你的代码后缀是.cpp, 他会调用g++编译器,当然library call也是c++版本的。当然我说了这么多你可能感到有些混乱,没关系,你就把gcc当成c语言编译器,g当成c语言编译器用就是了。

安装

  • sudo apt-get install g++
  • g++ --version 判断是否安装成功

gcc编译的四个步骤

gcc编译程序可分为四个步骤:预处理 --> 编译 --> 汇编 --> 链接
image.png

gcc常用参数

  • -I:指定头文件所在的目录
  • -c:只做预处理、编译、汇编,得到二进制文件
  • -g:编译时添加调试语句,主要用于gdb调试
  • Wall:显示所有警告信息
  • '-D':向程序中动态注册宏定义
  • '-O':

数据段合并

image.png
图例解释:

  • .text:存放程序运行代码(机器码)
  • .rodata:只读数据段
  • .data:存放了经过初始化的全局变量和静态变量
  • .bss:保存了那些用到但未被初始化的数据

地址回填

在代码内调用自己的函数有一个统一的地址,在程序未执行时 main 函数地址为0,假设代码如下

#include<stdio.h>

void fun1(){
}
void fun2(){
}
int main(){
    fun1();
    fun2();
}

在程序未执行时,代码中的函数都是没有地址的,fun1fun2函数的地址为main函数的地址加上一个数值,也就是,代码中剩余的函数地址是基于main的,地址为main地址 + x,当程序开始执行时,内存会分给main函数确切的地址,此时会把原来代替的地址回填到main地址 + x中,该过程为地址回填。