• 【Linux03-基本工具之GCC】Linux下的C语言编译器


    前言

    接上篇,继续学习基本工具。

    三、gcc

    是什么

    Linux下的C语言编译器(C++的编译器是g++,用法选项基本一样)。

    既然是编译器,我们就再来加点餐……
    在这里插入图片描述

    链接其实分为两种类型:静态链接和动态链接,分别需要静态库和动态库。


    加餐

    动态链接

    编译期间什么都不做,准备执行时,通过链接文件,将动态库载入内存。

    • 外部库变化影响程序
    • 可执行程序小
    静态链接

    编译期间把静态库的代码拷贝一份,编译完库就在可执行文件中。

    • 外部库变化不影响程序
    • 可执行程序大(重复包含更是十分冗余)
    动态库

    .so为后缀,程序准备运行时加载。

    静态库

    .a为后缀,程序编译时拷贝。

    函数库名称

    Linux下库的命名

    动态库:libXXX.so

    静态库:libYYY.a

    去掉前缀"lib"和后缀".so"/".a"就是库名。

    *windows下,动态库:.dll,静态库:.lib


    怎么用

    • -E:编译,预处理完停下,可-o指定生成.i文件
    • -S:编译,汇编完停下,可-o指定生成.s文件
    • -c:编译,链接完停下,可-o指定生成.o文件
    • -o:编译,指定生成目标文件(直接-o生成可执行文件)
    • -std=c99:指定c99标准

    首先看一下怎么在Linux上编译并运行一段代码:

    [bacon@VM-12-5-centos 2-vim]$ cat test.c
    #include 
    
    #define NUM(n) n 
    
    int main()
    {
        //1111
        //2222
        //3333
        printf("hello vim %d\n",NUM(1));
        printf("hello vim %d\n",NUM(2));
        printf("hello vim %d\n",NUM(3));
        return 0;
    }
    [bacon@VM-12-5-centos 2-vim]$ gcc test.c -o test
    [bacon@VM-12-5-centos 2-vim]$ ls
    test  test.c
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    有了可执行程序,如何执行呢?

    “./ + 可执行程序名”,找到路径即可执行。

    [bacon@VM-12-5-centos 2-vim]$ ./test 
    hello vim 1
    hello vim 2
    hello vim 3
    
    • 1
    • 2
    • 3
    • 4

    那我们如何知道可执行程序是动态链接还是静态链接呢?

    file [文件]

    [bacon@VM-12-5-centos 2-vim]$ file test
    test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=896e927d85e4e51f3f11ab910c017db042736fbf, not stripped
    
    • 1
    • 2

    能够知道:Linux默认选择动态动态链接。

    我们还能查看它依赖的动态库——ldd [文件]

    [bacon@VM-12-5-centos 2-vim]$ ldd test
    	linux-vdso.so.1 =>  (0x00007fffe77c2000)
    	libc.so.6 => /lib64/libc.so.6 (0x00007fc7e976f000)
    	/lib64/ld-linux-x86-64.so.2 (0x00007fc7e9b3d000)
    
    • 1
    • 2
    • 3
    • 4

    我们去掉 “libc.so.6 => /lib64/libc.so.6 (0x00007fc7e976f000)” 的"lib"和后缀:c。

    这就是c库。"0x00007fc7e976f000"就是我们依赖(需要)部分的起始位置。

    [bacon@VM-12-5-centos 2-vim]$ ls -l /lib64/libc.so.6
    lrwxrwxrwx 1 root root 12 Jul 25 16:58 /lib64/libc.so.6 -> libc-2.17.so
    [bacon@VM-12-5-centos 2-vim]$ ls -l /lib64/libc-2.17.so
    -rwxr-xr-x 1 root root 2156592 May 19  2022 /lib64/libc-2.17.so
    
    • 1
    • 2
    • 3
    • 4

    原来,所谓"libc.so.6"是链接文件,链接到libc-2.17.so这个库,库的大小也能看到。

    但,我们若有很多个程序都用这个动态库,不还是有很多份?

    并没有,动态库只加载需要的部分,而且是共享的,所以也叫共享库。

    如果我们想静态链接呢?

    gcc -static

    [bacon@VM-12-5-centos 2-vim]$ gcc test.c -static -o test_static 
    [bacon@VM-12-5-centos 2-vim]$ ll
    total 2
    -rwxrwxr-x 1 bacon bacon   8360 Dec  1 08:17 test
    -rwxrwxr-x 1 bacon bacon 861216 Dec  1 14:55 test_static
    [bacon@VM-12-5-centos 2-vim]$ file test_static 
    test_static: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=41f78cd6e97888d4295faa223090fd1d406097a3, not stripped
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    文件大小直接是百倍差距了。

    *系统默认带动态库(系统运行需要它——Linux大部分指令是C写的),但不一定有静态库(可能需要自己安装)。

    [bacon@VM-12-5-centos 2-vim]$ ls /usr/bin/which
    /usr/bin/which
    [bacon@VM-12-5-centos 2-vim]$ ldd /usr/bin/which
    	linux-vdso.so.1 =>  (0x00007ffd21fae000)
    	libc.so.6 => /lib64/libc.so.6 (0x00007f8c708f8000)
    	/lib64/ld-linux-x86-64.so.2 (0x00007f8c70cc6000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    到这我们也能知道,系统为了支持我们编程,提供了动静态库(定义)和其.h文件(声明)。所以,

    我的代码 + 库的代码(链接.lib和.o文件) = 可执行程序。


    接下来,我们用gcc的选项一步步看程序编译的过程

    -E 生成.i文件

    [bacon@VM-12-5-centos 2-vim]$ ls
    test.c
    [bacon@VM-12-5-centos 2-vim]$ gcc test.c -E -o test.i
    [bacon@VM-12-5-centos 2-vim]$ ls
    test.c  test.i
    [bacon@VM-12-5-centos 2-vim]$ vim test.i
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    -S 生成.s文件

    [bacon@VM-12-5-centos 2-vim]$ gcc test.c -S -o test.s
    [bacon@VM-12-5-centos 2-vim]$ vim test.s
    
    • 1
    • 2

    在这里插入图片描述

    -c 生成.o文件

    [bacon@VM-12-5-centos 2-vim]$ gcc test.c -c -o test.o
    [bacon@VM-12-5-centos 2-vim]$ vim test.o
    
    • 1
    • 2

    在这里插入图片描述

    以上是对于编译型语言,而对于解释型语言的一种运行方法:编辑完成后,给文件加上可执行属性就可以"./ filename"运行


    今天的分享就到这里啦

    这里是培根的blog,期待与你共同进步,下期见!

  • 相关阅读:
    关于vuex仓库管理
    面试官:Redis基本命令有哪些,Redis怎么实现分布式锁?
    快手双核心时代宣告结束,互联网“退休潮”还在继续?
    【JeecgBoot】Mac M1 微服务启动JeecgBoot + 启动JeecgBoot-vue3版本
    /sysdeps/aarch64/start.S:84:对‘main’未定义的引用
    【C++设计模式之状态模式:行为型】分析及示例
    reflow-回流 和 repaint-重绘
    计算机图形学实验——2023-09-28
    RHCE之web服务器搭建
    [go学习笔记.第十一章.项目案例] 2.客户信息管理系统
  • 原文地址:https://blog.csdn.net/BaconZzz/article/details/128204205