原作者 :http://blog.chinaunix.net/uid-11983311-id-2793921.html
本篇文章旨在介绍如何开始在linux下面进行C语言程序设计,以及如何使用程序设计及调试工具进行编写C程序。学会使用gcc及gdb等工具进行linux下的c编写和调试。
在开始之前,首先要说明的是,linux开发程序最主要的编辑器是vi/vim编辑器,当然还有emacs,gedit,只是vi/vim的用户实在是压倒性的多数,原因就是,它在编辑效率上的战胜了其他对手。vim是vi的升级版,带有关键字高亮显示及语法检查功能,现在很多的linux发行版都内置了它。
gcc是一个非常强大的编译工具,几乎可以编译linux下所有的c语言分支,当然主指还是在ANSI C上,虽然还有其他的编译器也可以在linux平台来编译C/C++,如intel的C compiler,不过,gcc的好处在于它集成于linux中,能够更加高效和方便的编译C/c++程序。
首先,让我们以一个程序设计界最经典的例子开始,就是HELL_WORLD程序,来推开linux C 语言设计的大门。
编写源程序: 使用vim来创建一个C语言源程序:
[bruce@server1 ~]$ vim hello_world.c
/*This is my first C program*/
#include
int main()
{
printf("Hello World!\n");
return 0;
}
在vim编辑器中,按esc再打入:wq保存退出即完成源程序的编写了。
编译源程序一:下面开始编译,使用的是gcc工具
[bruce@server1 ~]$ gcc hello_world.c
[bruce@server1 ~]$
编译完成后,没有给我们任何的回显信息,证明没有出现编译问题。
然后我们就来检查一下,编译之后有何变化,在当前目录下使用ls查看目录内容,我们可以看到多了一个a.out出来,其实它就是编译后产生的可执行文件,默认名就为a.out
[bruce@server1 ~]$ ls
a.out hello_world.c rpmbuild RPM-GPG-KEY-CentOS-3
Desktop programs rpmbuild.txt
[bruce@server1 ~]$
执行程序:然后我们可以像执行shell脚本一样的方式来执行它:
[bruce@server1 ~]$ ./a.out
Hello World!
[bruce@server1 ~]$
从上面我们可以看出,结果已经正常输出了。
再谈编译:像上面那样,虽然可以正常的编写编译程序,但问题也来了,如果当前目录下有多个源程序,那每次编译后都产生的a.out会被后一个a.out所重写,就达到我们的要求了,所以我们可以使用一些参数来指定编译之后的可执行程序名,以用来提高识别。
如上例中的hello_world.c,我们可使用如下方式编译,完成后输入ls查看:
[bruce@server1 ~]$ gcc hello_world.c -o hello_world
[bruce@server1 ~]$ ls
a.out hello_world programs rpmbuild.txt
Desktop hello_world.c rpmbuild RPM-GPG-KEY-CentOS-3
[bruce@server1 ~]$
我们可以发现,上面多了一个hello_world文件,这就是刚才我们使用-o参数所指定的输出程序名,然后我们可以像上面一样来执行它:
[bruce@server1 ~]$ ./hello_world
Hello World!
[bruce@server1 ~]$
可以看到,执行结果是一样的,这样子,即使你当前目录下有再多个源程序,也不会因此程序结果被重写了,大大提高了程序的识别的结果的正确性,同时我们可以全用更多的参数来实现其他的一些功能。
我们在此要说的是一个很重要的,也是很多linux的C开发者经常会用到的一个参数,就是代码优化功能,当你的程序中出现的运算次数越大,优化越明显示。这个参数就是-On参数,n可取自然数,比较典型的范围是从0变化到2或是3。具体的不在此详述了,参见man page.
以上我们介绍了,编写和编译linux的一些方法,相比较之下,是不是在linux平台要方便很多呢,其实都差不多,linux也是需要IDE的,只是linux本身就是一个大的IDE环境,所以并不像windows那样需要另外安装编译环境。另外据一些专家测试,在使用gcc的方法上,编译效率要高出其他IDE20%-30%,并且如果加上一些前端支持,就可以来编译Java,fortran,pascal等等。
程序的调试
程序的调试是一个很重要的环节,windows IDE下那些强大的调试功能,Linux以什么来对比呢,当然,在我看来,无所不能的linux一样可以胜任调试工作,有过之而无不及,那就是安装开发工具后,另一个集成于linux中的工具,gdb。
它是一款由GNU组织开发并发布的UNIX/Linux下的程序调试工具,虽然它没有图形化的友好界面,但是它功能异常强大,足以和其他一些商业化的IDE环境相媲美。
这时要说的是,调试的对像是可执行文件,而不是以".c"结尾的源代码文件,也就是说,源码文件,需要经过gcc编译之后生成哥执行文件才能用gdb调试。
下面就来介绍它的使用,像上面一样,我们参照一个源程序:
[bruce@server1 programs]$ vim smallest.c
//find the minimal between 2 INT Number
#include
int min(int x, int y);
int main()
{
int num1,num2,min_num;
printf("Please Input the first Number:\n");
scanf("%d",&num1);
printf("Please Input the second Number:\n");
scanf("%d",&num2);
min_num=min(num1,num2);
printf("The minimal one is %d\n", min_num);
}
int min(int a, int b)
{
if(a<b)
return a;
else
return b;
}
~
程序已经写在了上面,下面我们就来看一下如何产生带有调试信息的编译文件,这里我们要使用gcc的-g参数,用于在编译文件中加入一些调试信息。
[bruce@server1 programs]$ gcc -g smallest.c -o smallest
[bruce@server1 programs]$ ls
hello_world hello_world.c smallest smallest.c
从上面我们可以看出,有一个smallest产生出来,如果你想验证加上参数g后的变化,那么你可以不加g编译一次,然后比较其大小,你会发现,加上g后,产生的编译文件体积也会增加,所以在我们做软件开发时,加入调试信息应该在初期设计时,后期时,就应用去掉这些调试信息,当然如果想保留软件自身的调试功能,就要保留了。
言归正传。
使用gdb命令运行编译文件时,就可以看到如下信息,像其他的工具一样带有一些说明文字,包含一些版权、版本及其他说明,最后的(gdb)就是其环境提示符,类似于shell提示符,用于提醒用户,在此后面输入命令。
[bruce@server1 programs]$ gdb smallest
GNU gdb Fedora (6.8-27.el5)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(gdb)
下面来说一些常用的gdb调试命令
list 或是l 用于列出源程序
每打入一次list或是l将显示10行源代码,或是指定列出的行号来查看源程序 “list 行号”
使用此参数时,要确保源程序没有被移除或移动位置,否则无法查看。
break/b 设置断点,可指定断点行号,或是函数名等。
info break 显示断点信息
run 运行程序
print 查看程序运行时对应表达式的和变量的值
next 单步运行程序,但不进入函数调用
step 单步运行程序,且进行函数调用
continue 继续执行函数,直至函数结束或是下一个断点
下面以smallest.c程序来挨个讲解gdb这几个常用命令的用法
----- list/l, 如下示例
[bruce@server1 programs]$ gdb smallest
GNU gdb Fedora (6.8-27.el5)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(gdb) l
1 //find the minimal between 2 INT Number
2 #include
3 int min(int x, int y);
4 int main()
5 {
6 int num1,num2,min_num;
7 printf("Please Input the first Number:\n");
8 scanf("%d",&num1);
9 printf("Please Input the second Number:\n");
10 scanf("%d",&num2);
(gdb) list 12
7 printf("Please Input the first Number:\n");
8 scanf("%d",&num1);
9 printf("Please Input the second Number:\n");
10 scanf("%d",&num2);
11 min_num=min(num1,num2);
12 printf("The minimal one is %d\n", min_num);
13 }
14
15 int min(int a, int b)
16 {
(gdb)
大家可以看到它list/l的功能了吧,非常的简单,适合于手工检查程序语法错误,多个逗号,少个分号的情况,也就可以从这看得到了,当然这种错误,gcc也会告诉你的。
-----break/b,设置数点,如下:
(gdb) b 12
Breakpoint 1 at 0x8048448: file smallest.c, line 12.
(gdb) break min
Breakpoint 2 at 0x804846a: file smallest.c, line 17.
(gdb)
然后我们再看下一个命令
-----info break/b 显示断点信息
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048448 in main at smallest.c:12
2 breakpoint keep y 0x0804846a in min at smallest.c:17
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048448 in main at smallest.c:12
2 breakpoint keep y 0x0804846a in min at smallest.c:17
(gdb)
我们从上面显示可以看出,info break打印出了,我们先前设置好的两个断点,一个是在main函数的第12行,另外一个是在min函数。
下面就可以来运行程序了
-----run/r, 运行程序。
可以打入一个r,也可以输全run来运行程序:
(gdb) r
Starting program: /home/bruce/programs/smallest
Please Input the first Number:
12
Please Input the second Number:
14
Breakpoint 2, min (a=12, b=14) at smallest.c:17
17 if(a<b)
(gdb)
可以看到,停在了我们行鐩设置的断点min函数处。
下面我们来分步执行函数,
-----step,单步执行
示例是接着上面的例子继续执行的
Breakpoint 2, min (a=12, b=14) at smallest.c:17
17 if(a<b)
(gdb) step
18 return a;
(gdb) step
21 }
(gdb) step
Breakpoint 1, main () at smallest.c:12
12 printf("The minimal one is %d\n", min_num);
(gdb) step
The minimal one is 12
13 }
(gdb)
可以看到,执行step时,是按照顺序一步一步执行的,并且在min函数的断点处进入了函数体执行,直至结束,当然我们也可以换成next来执行,只不过next不进入函数体内部,把函数当成一个执行步骤来执行。
以上就是几个常用的gdb内部命令了,有一个地方需要提一下的是,当我们在执行到断点时,为了方便测试,我们可以在这个地方为已定义的变量赋值,只需在gdb提示符下输入: set 变量名=值
然后打入continue继续执行就可以了。
这篇文章介绍了linux下编辑,编译和调试程序的基本方法,使用的是vim/vi、gcc以及gdb的组合来进行c程序设计,其中有更多的玄妙之处,期待着大家在使用的时候去发现,本文仅是介绍一下概况,供参考。
OK,关于linux C语言开发的开始部分,就到这里了!