当前位置:   article > 正文

5.C语言 GCC总结_/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-li

/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/scrt1.o: in functi

gcc(GNU编译器套件)_百度百科GCC(GNU Compiler Collection,GNU编译器套件)是由GNU开发的编程语言译器。GNU编译器套件包括C、C++、 Objective-C、 Fortran、Java、Ada和Go语言前端,也包括了这些语言的库(如libstdc++,libgcj等。)GCC的初衷是为GNU操作系统专门编写的一款编译器。GNU系统是彻底的自由软件。此处,“自由”的含义是它尊重用户的自由。https://baike.baidu.com/item/gcc/17570

 在使用gcc编译程序时,编译过程可以细分为4个阶段:
1.预处理(Pre-Processing)
2.编译(Compiling)
3.汇编(Assembling)
4.链接(Linking)

  1. gcc -o main -v main.c
  2. -v:vebose
  3. //显示整个编译过程
  4. //gcc -v xx(可执行)就会显示其编译过程中不同阶段的信息

1.预处理(Pre-Processing)

  1. gcc -E main.c -o main.i
  2. //-E:macro expansion 宏展开,.i:intermediate 中间产物
  3. //没有-o main.i,则默认打印到标准输出
  4. cpp main.c
  5. //是gcc -E main.c的底层真正执行的命令
  6. //cpp : C Preprocessor的缩写
  1. 命令
  2. /usr/bin/x86_64-linux-gnu-cpp-9 main.c -o main.i
  3. 详细过程
  4. [root@Orz 23:40 /mnt/d/linux/c]# whereis cpp
  5. cpp: /usr/bin/cpp /usr/lib/cpp /usr/share/man/man1/cpp.1.gz
  6. [root@Orz 23:40 /mnt/d/linux/c]# ll /usr/bin/cpp
  7. lrwxrwxrwx 1 root root 5 Mar 20 2020 /usr/bin/cpp -> /usr/bin/cpp-9
  8. [root@Orz 23:40 /mnt/d/linux/c]# ll /usr/lib/cpp
  9. lrwxrwxrwx 1 root root 21 Nov 16 03:00 /usr/lib/cpp -> /etc/alternatives/cpp*
  10. [root@Orz 23:42 /mnt/d/linux/c]# ll /etc/alternatives/cpp
  11. lrwxrwxrwx 1 root root 12 Nov 16 03:00 /etc/alternatives/cpp -> /usr/bin/cpp*
  12. [root@Orz 23:43 /mnt/d/linux/c]# ll /usr/bin/cpp-9
  13. lrwxrwxrwx 1 root root 22 Aug 8 2020 /usr/bin/cpp-9 -> x86_64-linux-gnu-cpp-9*
  14. [root@Orz 23:44 /mnt/d/linux/c]# ll /usr/bin/x86_64-linux-gnu-cpp-9
  15. -rwxr-xr-x 1 root root 1158288 Aug 8 2020 /usr/bin/x86_64-linux-gnu-cpp-9*
  16. [root@Orz 23:49 /usr/bin]# ll /usr/bin | grep "gcc"
  17. -rwxr-xr-x 1 root root 428 May 7 2006 c89-gcc*
  18. -rwxr-xr-x 1 root root 454 Apr 11 2011 c99-gcc*
  19. lrwxrwxrwx 1 root root 5 Mar 20 2020 gcc -> gcc-9*
  20. lrwxrwxrwx 1 root root 22 Aug 8 2020 gcc-9 -> x86_64-linux-gnu-gcc-9*
  21. lrwxrwxrwx 1 root root 8 Mar 20 2020 gcc-ar -> gcc-ar-9*
  22. lrwxrwxrwx 1 root root 25 Aug 8 2020 gcc-ar-9 -> x86_64-linux-gnu-gcc-ar-9*
  23. lrwxrwxrwx 1 root root 8 Mar 20 2020 gcc-nm -> gcc-nm-9*
  24. lrwxrwxrwx 1 root root 25 Aug 8 2020 gcc-nm-9 -> x86_64-linux-gnu-gcc-nm-9*
  25. lrwxrwxrwx 1 root root 12 Mar 20 2020 gcc-ranlib -> gcc-ranlib-9*
  26. lrwxrwxrwx 1 root root 29 Aug 8 2020 gcc-ranlib-9 -> x86_64-linux-gnu-gcc-ranlib-9*
  27. lrwxrwxrwx 1 root root 5 Mar 20 2020 x86_64-linux-gnu-gcc -> gcc-9*
  28. -rwxr-xr-x 1 root root 1154192 Aug 8 2020 x86_64-linux-gnu-gcc-9*
  29. lrwxrwxrwx 1 root root 8 Mar 20 2020 x86_64-linux-gnu-gcc-ar -> gcc-ar-9*
  30. -rwxr-xr-x 1 root root 35464 Aug 8 2020 x86_64-linux-gnu-gcc-ar-9*
  31. lrwxrwxrwx 1 root root 8 Mar 20 2020 x86_64-linux-gnu-gcc-nm -> gcc-nm-9*
  32. -rwxr-xr-x 1 root root 35464 Aug 8 2020 x86_64-linux-gnu-gcc-nm-9*
  33. lrwxrwxrwx 1 root root 12 Mar 20 2020 x86_64-linux-gnu-gcc-ranlib -> gcc-ranlib-9*
  34. -rwxr-xr-x 1 root root 35464 Aug 8 2020 x86_64-linux-gnu-gcc-ranlib-9*

使用-E参数可以让gcc在预处理结束后停止编译过程,

工作内容:

1.处理#include预编译指令:递归地引入要include的文件,insert到预编译指令所在的位置

2.处理条件预编译指令:比如#if、#ifdef、#elif、#else、#endif,分析逻辑关系,然后删除这些预编译指令,只留下想要的代码

3.对#define预处理命令,进行宏展开,也就是字面值替换

4.把所有的注释全部删除

5.添加行号和文件名标识,以便于在编译过程中产生编译错误或者调试时都能够生成行号信息。

预处理器(cpp)根据以字符#开头的命令,修改原始的C程序,把宏定义进行替换。

另外可以使用gcc main.c -I 头文件的路径 -o main

2.编译(Compiling)

  1. gcc -S main.i -o main.s
  2. 命令
  3. /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu main.c -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase main -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o main.s
  4. 详细过程
  5. [root@Orz 00:09 /mnt/d/linux/c]# ll /usr/lib/gcc/x86_64-linux-gnu/9/cc1
  6. -rwxr-xr-x 1 root root 25654616 Aug 8 2020 /usr/lib/gcc/x86_64-linux-gnu/9/cc1

编译器(cc1)将文本文件main.i文件看成是预处理后的C语言源代码,再翻译成文本文件main.s,它包含一个汇编语言程序。

3.汇编(Assembling)

  1. gcc -c main.s -o main.o
  2. as -v --64 -o main.o main.s
  3. 命令
  4. /usr/bin/x86_64-linux-gnu-as -v --64 -o main.o main.s
  5. 详细过程
  6. [root@Orz 00:03 /mnt/d/linux/c]# whereis as
  7. as: /usr/bin/as /usr/share/man/man1/as.1.gz
  8. [root@Orz 00:04 /mnt/d/linux/c]# ll /usr/bin/as
  9. lrwxrwxrwx 1 root root 19 Oct 20 19:09 /usr/bin/as -> x86_64-linux-gnu-as*
  10. [root@Orz 00:05 /mnt/d/linux/c]# ll /usr/bin/x86_64-linux-gnu-as
  11. -rwxr-xr-x 1 root root 696624 Oct 20 19:09 /usr/bin/x86_64-linux-gnu-as*

汇编器(as)将main.s翻译成机器语言指令,把这些指令打包成一种可重定位目标程序的格式,并将结果保存在目标文件main.o中。main.o文件是一个二进制文件,它的字节编码是机器语言指令而不是字符,如果我们在文本文件中打开main.o文件,看到的将是一堆乱码。

4.链接(Linking)

  1. gcc -v main.o -o main 可以看见详细过程
  2. 命令
  3. /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccZ7lCdk.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o main /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. main.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
  4. 1779 whereis ld
  5. 1780 ll /usr/bin/ld
  6. 1781 ll /usr/bin/x86_64-linux-gnu-ld
  7. 1782 ll /usr/bin/x86_64-linux-gnu-ld.bfd

链接器(ld)负责处理合并目标代码,生成一个可执行目标文件,可以被加载到内存中,由系统执行

GCC基本使用方法、常用指令

  1. gcc [options] [filenames] -o [outputfilename]
  2. /*其中options就是编译器所需要的参数;filenames给出相关的文件名称,可同时给出多个文件;
  3. outputfilename为生成文件名称。*/
  4. [options]
  5. -c:通知gcc取消连接步骤,即编译源码并在最后生成目标文件
  6. -Dmacro:定义指定的宏,使它能够通过源码中的#ifdef进行检验
  7. -E:不经过编译预处理程序的输出而输送至标准输出
  8. -g3:获得有关调试程序的详细信息,它不能与-o选项联合使用
  9. -Idirectory:在包含文件搜索路径的起点处添加指定目录
  10. -llibrary:提示连接程序在创建最终可执行文件时包含指定的库
  11. -O、-O2、-O3:将优化状态打开,该选项不能与-g选项联合使用
  12. -S:要求编译程序生成来自源代码的汇编程序输出
  13. -v:启动所有警报
  14. .h:预处理文件(标头文件)
  15. -Wall:在发生警报时取消编译操作,即将警报看作是错误
  16. -w:禁止所有的报警

(2条消息) GCC_人生代码 ---- 公众号-CSDN博客https://blog.csdn.net/qq_36772866/article/details/91126586?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163695872216780357234289%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163695872216780357234289&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-4-91126586.first_rank_v2_pc_rank_v29&utm_term=gcc&spm=1018.2226.3001.4187

HelloWorld背后的故事:在Linux上编译C语言程序_朝闻道-夕死可矣的博客-CSDN博客C语言的经典程序“Hello World”并不难写,很多朋友都可以闭着眼将它写出来。那么编译一个“Hello World”到底经历了怎样的过程呢?从源代码到可执行文件我们将这个文件命名为hello.c:#include <stdio.h>int main() { printf("Hello World\n"); return 0;}程序的第一行引用了stdio.h,stdio.h里有一些C标准库预定义好的方法,比如printf()方法,...https://blog.csdn.net/jc_benben/article/details/113945697

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/189264
推荐阅读
相关标签
  

闽ICP备14008679号