Chinaunix首页 | 论坛 | 博客
  • 博客访问: 841130
  • 博文数量: 116
  • 博客积分: 1472
  • 博客等级: 上尉
  • 技术积分: 1725
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-06 11:45
文章分类

全部博文(116)

文章存档

2015年(1)

2014年(42)

2013年(5)

2012年(19)

2011年(49)

我的朋友

分类: C/C++

2014-01-11 08:19:57

一、单个C源文件的编译(参数-o)
   前面的例子中提到将一个C源文件编译成可执行文件的方法,标准格式如下:
   gcc -o 目标文件 源文件
   如前面的例子中的 gcc -o testGcc test.c
二、多个C源文件的编译(参数-c和-o)
   上面我们看到,对于一个文件,我们可以直接编译成可执行文件。实际的开发过程中,可能由很多人同时开发,每个人只开发部分的C源程序,最后再连接成一个可执行程序。假定下面的两个文件是分别由两个人开发的,我们来看看工作的过程。
    程序员甲编写了testmain.c程序如下:
   

点击(此处)折叠或打开

  1. //file name is testmain.c
  2.     #include <stdio.h>
  3.     int main()
  4.     {
  5.       int m;
  6.       printf("Enter an integer\n");
  7.       scanf("%d",&m);
  8.       printf("absolute value is %d\n" , absf(m));
  9.       return 0;
  10.     }

    程序员乙编写了testsub.c程序如下:
    //file name is testsub.c
    int absf(int a)
    {
      if(a<0){
        return -a;
      }else{
        return a;
      }
    }
程序员甲编写完自己的程序后就要进行编译,以确认程序的语法是否正确。如果执行前面提到过的语句
gcc -o test2.exe testmain.c会提示未定义的参照absf。这是程序员乙的文件testsub.c中的函数。
所以,程序员甲在编译时要用另外的参数-c来编译,执行gcc -c testmain.c,生成testmain.o文件。
testmain.o这个文件是不可执行的,但在编译过程中能够检查出是否存在语法错误。

而程序员乙也用同样的方式编译testsub.c,执行gcc -c testsub.c,生成testsub.o文件。

最后再用-o参数来连接到一起:

执行 gcc -o test.exe testmain.o testsub.o 生成最终的test.exe就可以运行了。当然,扩展名exe在linux系列的系统中是没有什么实际意义的。这里主要是让习惯于使用windows的开发人员更容易理解已经编译出一个可执行程序罢了。

三、如何调试C语言程序(参数-g、命令l、命令b、命令p、命令n、命令s、命令c、命令q)

我们上面的例子程序是没有什么严重错误的,都可以编译通过,并且能够执行。实际的开发过程中就不一定这么幸运了,经常会遇到这种情况,就是程序虽然可以通过编译,但一运行就出错。这就要用到Ubuntu下的调试工具gdb了。

1、用gdb调试之前,要将调试信息编译到目标程序中,需要用到相关的参数-g,按照下面的步骤重新编译上面的两个C源文件。执行gcc -c -g testmain.c和gcc -c -g testsub.c,然后连接这两个程序,gcc -o test.exe testmain.o testsub.o。现在生成的test.exe文件中已经带有调试过程中所需要的信息。如果只有一个源文件的情况下可以直接使用“gcc -g 源文件名”的方式来编译成可执行文件,而不需要两步编译了。

2、调试状态下运行,执行gdb test.exe。执行后提示符变成(gdb),表示已经在调试状态下。

3、调试状态下查看源文件,在(gdb)提示符下执行l命令(小写的L),显示程序信息如下。显示的程序中加入了行号。

    1    #include
    2    int main()
    3    {
    4      int m;
    5      printf("Enter an integer\n");
    6      scanf("%d",&m);
    7      printf("absolute value is %d\n" , absf(m));
    8      return 0;
    9    }

4、设置断点命令b,可以在需要检查运行状况的语句处设置断点。比如在提示符(gdb)下,执行b 7,就在第7行的那个输出语句上设置了断点。

5、运行命令r,设置断点后,执行r,程序就开始运行了,按程序的提示我们输入一个负数-20并按回车后,程序会一直运行到我们设置的断点处停下来,并将那一行显示出来,如“7      printf("absolute value is %d\n" , absf(m));”。

6、查看变量值命令p,比如在提示符(gdb)下,执行p m,可以查看断点处变量m的值,显示$1 = -30。如果输入p absf(m),则显示$2 = 30,

7、单行继续执行命令n和s,在提示符(gdb)下,n表示执行下一条语句,如果下一条语句中有我们编写的函数,我们想执行到函数内部的话,就可以用s命令。比如上面运行到7这条语句停下来之后,我们输入s命令就可以入到函数absf内部,然后再一行一行地调试。

8、多行继续执行命令c,如果要运行程序剩余的部分,在提示符(gdb)下,输入c并按回车后,就可以继续运行下去。

9、退出调试状态命令q,当调试完成后,在提示符(gdb)下,输入q 并按回车后退出调试状态。

四、更多源文件的编译(make命令)

上面的例子中只有两个文件,更多的源文件在编译时关系要复杂的多,这是按上述编译方法已经无法满足需求。采用的办法是根据这些文件的依赖关系,把编译和连接的顺序记录到文件中。对这个文件就是makefile。

1、makefile规则:

    目标: 依赖1 依赖2

    命令1

    命令2

其中,目标就是我们让make做的事情;依赖就是做这个事情需要的相关文件;标示要输入一个tab键,注意这个不能用空格代替;命令就是具体要执行的shell命令。

2、对于前面提到的编译两个文件的例子,可以做成下面的makefile文件,放到源文件的目录下:

#makefile for test.exe
test.exe: testmain.o testsub.o  #目标1
 gcc -o test.exe testmain.o testsub.o  #开始有一个tab键
testmain.o: testmain.c  #目标2
 gcc -c -g testmain.c  #开始有一个tab键
testsub.o: testsub.c  #目标3
 gcc -c -g testsub.c  #开始有一个tab键
clean: testmain.o testsub.o  #目标4
 rm testmain.o  #开始有一个tab键
 rm testsub.o  #开始有一个tab键

3、make的执行(参数-f)

执行make -f makefile,这时实行ls就可以看到已经生成了我们需要的test.exe文件的可调试版本。

但同时还有两个中间文件testmain.o和testsub.o已经不需要了。

在make文件中已经定义了目标clean,就是为了清除中间文件,因此,执行make clean,就可以删除那两个中间文件。 

 

阅读(4213) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~