• Linux系统编程学习笔记


    1 前言

    1.1 环境

            平台:uabntu24.04

            工具:vim,gcc,make

    1.2 GCC

            

    Linux系统下的GCC(GNU Compiler Collection)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%。

    GCC编译器能将C、C++语言源程序、汇程式化序和目标程序编译、链接成可执行文件,如果没有给出可执行文件的名字,gcc将生成一个名为a.out的文件。

    GCC编译器编译C源文件为可执行文件的步骤:

    C源文件—->预处理.i—->编译.s(生成汇编文件)—->汇编.o/.obj(生成目标文件)—->链接.out(生成可执行文件)—->可执行文件
    gcc命令参数(选项)

    参数    含义    示例

    参数含义示例
    -c对文件进行预处理、编译和汇编,生成obj文件    gcc -c hello.c
    -S 只进行预处理和编译,生成汇编代码gcc -S hello.c
    -E只进行预处理,这个选项不生成文件,可以使用重定向或者-o选项使其生成一个文件 gcc -E hello.c > hello.i或者gcc -E hello.c -o hello.i
    -o 指定目标的名称,默认为a.outgcc -o hello hello.c


           
    过程演示

    例如源代码main.c:

    1. #include
    2. int main(void) {
    3. printf("Hello World!\n");
    4. return 0;
    5. }


    预编译:这个过程处理宏定义和include,去除注释,不会对语法进行检查。可以看到预编译后,源文件的代码从6行扩展了很多行,生成main.i

    1. gcc -E main.c > main.i # 或者 gcc -E main.c -o main.i
    1. // ...
    2. // 只展示了一部分
    3. extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
    4. extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
    5. # 943 "/usr/include/stdio.h" 3 4
    6. # 2 "main.c" 2
    7. int main(void) {
    8. printf("Hello World!\n");
    9. return 0;
    10. }


    编译:这个阶段,检查语法,生成汇编代码main.s

    gcc -S main.c -o main.s
    1. .file "main.c"
    2. .section .rodata
    3. .LC0:
    4. .string "Hello World!"
    5. .text
    6. .globl main
    7. .type main, @function
    8. main:
    9. .LFB0:
    10. .cfi_startproc
    11. pushq %rbp
    12. .cfi_def_cfa_offset 16
    13. .cfi_offset 6, -16
    14. movq %rsp, %rbp
    15. .cfi_def_cfa_register 6
    16. movl $.LC0, %edi
    17. call puts
    18. movl $0, %eax
    19. popq %rbp
    20. .cfi_def_cfa 7, 8
    21. ret
    22. .cfi_endproc
    23. .LFE0:
    24. .size main, .-main
    25. .ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
    26. .section .note.GNU-stack,"",@progbits


    汇编:这个阶段,生成目标代码main.o

    gcc -c main.s -o main.o


    链接:生成可执行代码main。
    链接分为两种,一种是静态链接,另外一种是动态链接。
    使用静态链接的好处是,依赖的动态链接库较少,对动态链接库的版本不会很敏感,具有较好的兼容性;缺点是生成的程序比较大。
    使用动态链接的好处是,生成的程序比较小,占用较少的内存。

    gcc main.o -o main

     运行

    1. [root@HongyiZeng c]# ./main
    2. Hello World!

    1.3 make

    make命令是GNU工程化中的一个编译工具。make是依赖于Makefile来编译多个源文件的工具。在Makefile里同样是用gcc(或者别的编译器)来编译程序。

    可以使用以下命令直接生成可执行文件:

    make main

    直接运行

    1. [root@HongyiZeng c]# ./main
    2. Hello World!

     1.4 makefile

    一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。

     1.4.1 使用gcc的例子

    创建文件:

    touch main.c tool1.c tool1.h tool2.c tool2.h

    可以使用vim * -p打开当前目录下的所有文件。-p是打开多个文件的选项。

    在命令模式下,gt切换到下一个标签页,gT切换到上一个标签页。

    退出多个标签时,可加上a,例如:qa或者:wqa等

    tool1.h和tool1.c

    1. #ifndef __TOOL1_H__
    2. #define __TOOL1_H__
    3. void mytool1();
    4. #endif
    1. #include
    2. #include "tool1.h"
    3. void mytool1() {
    4. printf("tool1 print...\n");
    5. }

    tool2.h和tool2.c

    1. #ifndef __TOOL2_H__
    2. #define __TOOL2_H__
    3. void mytool2();
    4. #endif
    1. #include
    2. #include "tool2.h"
    3. void mytool2() {
    4. printf("tool2 print...\n");
    5. }

    main.c

    1. #include "tool1.h"
    2. #include "tool2.h"
    3. int main(void) {
    4. mytool1();
    5. mytool2();
    6. return 0;
    7. }

    对所有文件进行编译:

    gcc *.c

    执行a.out

    1. [root@HongyiZeng makefile]# ./a.out
    2. tool1 print...
    3. tool2 print...

  • 相关阅读:
    【Cherno的OpenGL视频】How to make your uniform faster in OpenGL
    Chrome浏览器书签同步配置方法
    经典论文阅读之-GICP(ICP大一统)
    弘玑Cyclone2022年产品发布会:人人可用的数字化工作平台——弘玑工作易
    elementUI el-table+树形结构子节点选中后没有打勾?(element版本问题 已解决)
    CentOS遇到的麻烦与解决方案
    利用文本结构知识增强预训练模型的问题生成
    前端项目实战183-ant design Cascader实现自定义字段
    开源服务器大整理
    用飞书写博客,并自动部署
  • 原文地址:https://blog.csdn.net/weixin_47675625/article/details/139273870