GCC编译器

1.编译器主要组件

  • 分析器:将源语言程序代码转换为汇编语言
  • 汇编器:将汇编代码转换为CPU可执行的字节码
  • 链接器:将汇编器生成的单独目标文件组合成可执行的应用程序
  • 标准C库:在应用程序中用到C库中的函数,这个库就会通过链接器和源代码连接来生成最终可执行程序

2.GCC基本用法和选项

GCC基本用法是gcc [options] [filename]

  • -c,只编译,不连接成可执行文件,编译器只是由输入的.c等源代码生成以.o为后缀的目标文件,通常用来编译不包含主程序的子程序文件
  • -o output_filename,确定输出文件名称为output_filename,同时这个名称不能与源文件同名。如果不给输出文件名,则会默认生成a.out可执行文件
  • -g,产生符号调试工具(GUN的gdb)所必要的符号资讯,想要调试源代码,必须加入该选项
  • -O,对程序进行优化编译,对应编译,连接速度变慢
  • -O2,比-O更好地优化编译
  • -I dirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数
  • -L dirname,将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在链接过程中使用的参数

3.GCC常见错误类型及对策

  • C语法错误(syntex error)
  • 头文件错误(Can not find include file xx.h)
  • 档案库错误(ld: -lm: No such file or directory),即找不到库函数
  • 未定义符号(Undefined symbol)

4.GCC编译过程

#include 
#include 

#define N 10
#define _DEBUG_

int main(int argc, const char *argv[])
{
    int m = 10, n;
    m += N;
    n = sqrt(m);

#ifdef _DEBUG_
    printf("debug:m=%d n=%d\n", m, n);
#else
    printf("nodebug:m=%d n=%d\n", m, n);
#endif
    return 0;
}

注意:在此处用到math.h,在编译时候需要链接-lm(通过man sqrt查看sqrt函数手册)

hanqi@hanqi-PC:~/gccdemo$ gcc -o demo1 demo1.c -Wall -lm
hanqi@hanqi-PC:~/gccdemo$ ./demo1
debug:m=20 n=4
  • 预处理,.c文件变.i文件
    a.把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。
    b.预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。
    c.预处理器将源程序文件中出现的对宏的引用展开成相应的宏定义,即本文所说的#define的功能,由预处理器来完成。
hanqi@hanqi-PC:~/gccdemo$ gcc -E demo1.c -o demo1.i
  • 编译,.i文件变.s文件
    a.将预处理之后的代码转换为汇编代码
hanqi@hanqi-PC:~/gccdemo$ gcc -S demo1.i -o demo1.s
  • 汇编,.s文件变.o文件
    a.检查语法错误,生成汇编文件
    b.将汇编代码转换为机器码
hanqi@hanqi-PC:~/gccdemo$ gcc -c demo1.s -o demo1.o
  • 链接,.o文件变.exe文件
    a.将多个目标文件和其所对应的库链接为最终可执行文件
hanqi@hanqi-PC:~/gccdemo$ gcc demo1.o -o demo1 -lm

5.GDB调试流程

  • 使用gcc对.c进行编译,加上-g
hanqi@hanqi-PC:~/gccdemo$ gcc -g demo1.c -o demo1 -lm
hanqi@hanqi-PC:~/gccdemo$ gdb demo1.out
  • l,查看源码,多次l查看下一页源码,l num,跳转到第num页
(gdb) l
1   #include 
2   #include 
3   
4   #define N 10
5   #define _DEBUG_
6   
7   int main(int argc, const char *argv[])
8   {
9       int m = 10, n;
10      m += N;
(gdb) l
11      n = sqrt(m);
12  
13  #ifdef _DEBUG_
14      printf("debug:m=%d n=%d\n", m, n);
15  #else
16      printf("nodebug:m=%d n=%d\n", m, n);
17  #endif
18      return 0;
19  }
(gdb) l
Line number 20 out of range; demo1.c has 19 lines.
(gdb) l 1
1   #include 
2   #include 
3   
4   #define N 10
5   #define _DEBUG_
6   
7   int main(int argc, const char *argv[])
8   {
9       int m = 10, n;
10      m += N;
(gdb)
  • b num,在第num行设置断点
(gdb) b 9
Breakpoint 1 at 0x72f: file demo1.c, line 9.
(gdb) b 11
Breakpoint 2 at 0x73a: file demo1.c, line 11.
(gdb) 
  • info b,查看断点信息
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000072f in main at demo1.c:9
2       breakpoint     keep y   0x000000000000073a in main at demo1.c:11
(gdb) 
  • del num,删除第num个断点
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000072f in main at demo1.c:9
2       breakpoint     keep y   0x000000000000073a in main at demo1.c:11
(gdb) del 1
(gdb) info b
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000000073a in main at demo1.c:11
(gdb) 
  • q,退出调试
  • r, 运行代码
(gdb) r
Starting program: /home/hanqi/gccdemo/demo1 

Breakpoint 2, main (argc=1, argv=0x7fffffffcde8) at demo1.c:11
11      n = sqrt(m);
(gdb) 
  • p m,查看变量m的值
(gdb) p m
$1 = 20
(gdb) p n
$2 = 0
(gdb) 
  • n,单步运行跳过函数;s,单步运行进入函数
(gdb) n
14      printf("debug:m=%d n=%d\n", m, n);
(gdb) 
  • c,恢复程序运行
(gdb) c
Continuing.
debug:m=20 n=4
[Inferior 1 (process 34720) exited normally]
(gdb) 
  • set args 参数:指定运行时的参数
  • show args:查看设置好的参数
    部分参考链接:https://blog.csdn.net/niyaozuozuihao/article/details/91802994

你可能感兴趣的:(GCC编译器)