Linux学习笔记03 -- gcc编译器的基本使用

文章目录

  • 1.简介
  • 2.gcc编译器的主要组件
  • 2.编译
    • 1)编译过程
    • 2)常用的编译方式
    • 3)其他编译方式
  • 3.简单调试
  • 4.gcc调试c语言常见错误及对策
    • 1)C语法错误
    • 2)头文件错误
    • 3)档案库错误
    • 4)未定义符号

1.简介

gcc编译器(GNU compiler)是GNU推出的多平台编译器,可将C,C++源程序编译连接成可执行文件,支持以下后缀

  • .c:C语言源代码
  • .h:程序所包含的头文件
  • .i:已经预处理过的c源代码文件
  • .s:汇编语言源代码文件
  • .o:编译后的目标文件
  • .a/.so:编译后的库文件

2.gcc编译器的主要组件

  • 分析器:分析器将源语言程序代码转换为汇编语言。因为要从一种种格式转换为另一种格式(C到汇编),所以分析器需要知道目标机器的汇编语言
  • 汇编器:转换为另一种格式(C到汇编),所以分析器需要知道目标机器的汇编语
  • 链接器:链接器将汇编器生成的单独的目标文件组合成可执行的应用程序。链接器需要知道这种目标格式以便工作。
  • 标准库:核心的C函数都有一个主要的C库来提供。如果在应用程序中用到了C库中的函数,这个库就会通过链接器和源代码连接来生成最终的可执行过程。

2.编译

1)编译过程

编译的过程总共分为以下四步

  • 预处理(Pre_Processing)
  • 编译(Compiling)
  • 汇编(Assembling)
  • 链接 (Linking)

编译的过程通过gcc中主要的组件将源文件一步步转换陈可执行的二进制文件

Linux学习笔记03 -- gcc编译器的基本使用_第1张图片

编译命令使用过程简要如下

Linux学习笔记03 -- gcc编译器的基本使用_第2张图片

2)常用的编译方式

常用的编译过程有两种方式

  • gcc hello.c -o hello (推荐使用)
  • gcc -o hello hello.c

如下执行可执行文件

./hello

3)其他编译方式

其他参数gcc参数有如下所示

  • -o:编译正确之后输出另一个名字的可执行文件,不使用该参数将默认为a.out

  • -c:只要求编译器输出目标代码(.o文件),而不必输出可执行文件

  • -g:用于调试

  • -E:用于转换预处理过程

  • -0(零):对于程序进行优化编译,连接。提高效率的同时拖慢速度

  • -I dirname:将dirname所指向的目录加入到程序头文件目录列表中,用于预编译过程

  • -L dirname:将dirname所指向的目录加入到程序函数档案库文件的目录列表中,用于链接过程

  • -Wall:用于在编译时候检查语法是否符合规范,如下所示

    • gcc hello.c -o hello -Wall
      

3.简单调试

使用内置的调试函数,提高对信息的出错日志打印

  • __FILE__:打印出文件名,为字符类型
  • __FUNCTION__:打印出所在函数名,为字符类型
  • __LINE__:打印出所在行,为整型
printf("%s%s%d\n",__FILE__,__FUNCTION__,`__LINE__`);

4.gcc调试c语言常见错误及对策

1)C语法错误

  • 错误信息:文件source.c中第n行有语法错误(syntex error
  • 解决方法:重新进入文件查看相应的语法

2)头文件错误

  • 错误信息:找不到头文件head.h(can not find include file head.h
  • 解决方法:查看包含的头文件是否是目录名错误和双引号或者尖括号错误

3)档案库错误

  • 错误信息:链接程序找不到所需的函数库(ld : -lm: no such file or directory
  • 原因:能存在函数名错误、指定的函数库所在的目录名称错误等。
  • 解决方法:需要使用find命令在目录中查找出相应的函数库名,确定正确的函数名称。

4)未定义符号

  • 错误信息:有未定义的符号(Undefined symbol
  • 原因:
    • 1.使用者自己定义的函数或者全局变量所在源代码文件没有被编译连接,或者干脆没有定义
    • 2.为定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应函数库的名称
  • 解决方法:
    • 对于原因1:需要使用这根据实际情况修改源程序,给出全局变量或者函数的定义体或者干脆没有定义
    • 对于原因2.为定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应函数库的名称

你可能感兴趣的:(Linux)