第7章 C语言开发工具
实验目的
● 学习理解Linux环境中将C程序转换成可执行文件所经历的过程
● 学习使用Linux环境中将C程序转换成可执行文件所采用的命令
● 学习使用indent、gcc、make、gdb命令
实验指导
Linux操作系统提供了非常好的编程环境,Linux系统支持多种高级语言。C语言是Linux中最常用的系统编程语言之一,Linux内核绝大部分代码是用C语言编写的,Linux平台上的相当多的应用软件也是用C语言开发的。使用C语言,软件开发人员可以通过函数库和系统调用非常方便实现系统服务。另外,还有很多有用的工具为程序开发和维护提供便利。
Linux操作系统拥有许多用于程序的生成以及分析的软件工具。其中包括用于编辑和缩进代码、编译与连接程序、处理模块化程序、创建程序库、剖析代码、检验代码可移植性、源代
码管理、调试、跟踪以及检测运行效率等等的工具。在这一章里,我们将介绍一些常用的C语言工具,主要包括gcc、make工具。make工具可以用来跟踪那些更新过的模块,并确保在编译时使用所有程序模块的最新版本。
7.1 编写程序的工具
我们编写程序可以用Linux文本编辑器(如:pico编辑器、vi编辑器、gedit编辑器、emacs 编辑器和 xemacs编辑器)。
我们首先使用 vi 编辑器来编辑hello.c,这是一个 C 语言的文件。
$ vi hello.c
输入下列程序代码:
#include <sdtio.h>
#include <sdtlib.h>
int main()
{
int i, j;
for (i=0,j=10; i < j; i++)
{
printf("HELLO, LINUX WORLD\n");
exit(0)
}
}
我们使用 indent 命令来将hello.c自动调整C代码的缩进风格。默认情况下indent会按照GNU风格进行缩进,并保留用户输入的所有回车符。indent 命令简要描述如下。
命令语法:
indent [options] [sourcefilename-list]
indent [options] [sourcefilename] [-o outfilename]
常用选项:
-bad 在声明变量后空一行。
-bap 在函数体后空一行。
-bl 按Pascal方式缩进代码。
-bls 把结构体声明后的大括号放到单独的一行上。
-kr 以 Kernighan &Ritchie coding风格缩进代码。
-orig 按Berkeley风格缩进代码。
-st 把缩进后的结果送到标准输出。
注意:在以下两行注释之间的代码不会被indent缩进,注意*与INDENT, ON和OFF与*之间没有空格但你可以在两个*之间随意增加空格。
/**INDENT OFF**/
/**INDENT ON**/
例:使用 indent -st hello.c 将 hello.c 以标准格式输出。
$ indent -st hello.c
#include <sdtio.h>
#include <sdtlib.h>
int main()
{
int i, j;
for (i=0,j=10; i < j; i++)
{
printf("HELLO, LINUX WORLD\n");
exit(0)
}
}
例:使用 indent -kr -st hello.c 命令,将 hello.c 以 Kernighan &Ritchie coding风格缩进代码。
$ indent -kr -st hello.c
#include <sdtio.h>
#include <sdtlib.h>
int main()
{
int i, j;
for (i=0,j=10; i < j; i++){
printf("HELLO, LINUX WORLD\n");
exit(0)
}
}
linux下gcc编译的四个步骤7.2 编译C语言程序
7.2.1 gcc编译器
Linux下最常用的C编译器是GNU gcc()。gcc是一个ANSI C 兼容编译器。C++编译器(如g++,GNU compiler for C++)也可以用于编译C程序,事实上g++内部还是调用了gcc,只不过加上了一些命令行参数使得它能够识别C++源代码。我们主要介绍gcc编译器,它是Linux平台上应用最广泛的C编译器。
gcc 命令可以启动C编译系统,当执行gcc时,它将完成预处理、编译、汇编和连接4个步骤并最终生成可执行代码。产生的可执行程序默认被保存为a.out文件。gcc命令可以接受多种文件类型并依据用户指定的命令行参数对它们做出相应处理。这些文件类型包括静态链接库(扩展名为.a),C语言源文件(.c),C++源文件(.C, .cc或者.cpp),汇编语言源文件(.s),预处理输出文件(.i)和目标代码(.o)。如果gcc无法根据一个文件的扩展名决定它的类型,它将假定这个文件是一个目标文件或库文件。
命令语法:
gcc [options] filename-list
常用选项:
-
ansi 以ANSI标准。
-c 跳过连接步骤,编译成目标(.o)文件。
-g 创建用于gdb(GNU DeBugger)的符号表和调试信息。
-l库文件名 连接库文件。
-m类型 根据给定的CPU类型优化代码。
-o 文件名 将生成的可执行程序保存到指定文件中,而不是默认的a.out。
-O[级别] 根据指定的级别(0-3)进行优化;数字越大优化程度越高。如果指定级别为0(默认),编译器将不做任何优化。
-pg 产生供GNU剖析工具gprof使用的信息。
-S 跳过汇编和连接阶段,并保留编译产生的汇编代码(.s文件)。
-v 产生尽可能多的输出信息。
-w 忽略警告信息。
-W 产生比默认模式更多的警告信息。
gcc有100多个的编译选项。很多的gcc选项包括一个以上的字符,因此必须为每个选项指定各自的连字符, 并且就象大多数 Linux 命令一样不能在一个单独的连字符后跟一组选项。例如, 下面的两个命令是不同的:
gcc -p -g hello.c
gcc -pg hello.c
第一条命令告诉gcc编译hello.c 时为prof 命令建立剖析(profile)信息并且把调试信息加入到可执行的文件里;第二条命令只告诉gcc为gprof 命令建立剖析信息。
例:下面gcc命令,不带任何选项,编译后生成a.out可执行文件。./a.out是运行该程序,即在当前目录下查a.out文件。
$ gcc hello.c
$ ./a.out
例:下面gcc命令,带-o选项,编译后生成可执行文件名为hello
$ gcc -o hello hello.c
例:可以用-c选项编译成目标文件,下面命令中,前三个gcc编译后生成目标文件fd.o、fs.o、fm.o。最后一个gcc命令,连接已编译好的目标文件,生成可执行程序文件名为fall
$gcc -c fd.c
$gcc -c fs.c
$gcc -c fm.c
$gcc fd.o fs.o fm.o -o fall
7.2.2 函数库
函数库是一组预先编译好的函数的集合,这些函数都是按照可重用的原则编写的。它们通
常由一组相互关联的函数组成并执行某项常见的任务。
标准系统库文件一般存放在linux文件系统/lib和 /usr/lib目录中。C语言编译器需要知道要搜索哪些库文件,默认情况下,它只搜索标准C语言库。仅把库文件放在标准目录中,然后希望编译器到它是不够的,库文件必须遵循特定的命名规范并且需要在命令行中明确指定。
库文件的名字总是以lib开头,随后的部分指明这是什么库(例如,c代表C语言库,m代表数学库)。文件名的最后部分以.开始,然后给出库文件的类型:
.a 代表传统的静态函数库
.so代表共享函数库
例如,libm.a为静态数学函数库。
函数库通常以静态库和共享库两种格式存在,可用ls /usr/lib命令查看。我们可以通过给出完整的路径名或用-l标志来指示编译器要搜索的库文件。例如:
$ gcc -o hello hello.c /usr/lib/libm.a
这条命令指示编译器编译文件hello.c,将编译产生的程序文件命名为hello,并且除搜索标准的C语言函数库外,还搜索数学库以解决函数引用问题。下面的命令也能产生类似的结果:
$ gcc -o hello hello.c -lm
-lm(在字母l和m之间没有空格)是简写方式,它代表的是标准库目录(本例中是/usr/lib)中名为libm.a的函数库。-lm标志的另一个好处是如果有共享库,编译器会自动选择共享库。
虽然库文件和头文件一样,通常都保存在标准位置,但我们也可以通过-L(大写字母)标志为编译器增加库的搜索路径。例如:
$ gcc -o x11pro1 x11hello.c -L/usr/openwin/lib -lX11
这条命令用/usr/openwin/lib目录中的libX11库来编译和链接程序x11hello。
1. 静态库
函数库最简单的形式是一组处于“准备好使用”状态的目标文件。当程序需要使用函数库中的某个函数时,它包含一个声明该函数的头文件。编译器和链接器负责将程序代码和函数库结合在一起以组成一个单独的可执行文件。我们必须用-l选项指明除标准C语言运行库外还需使用的库。
静态库,也称作归档库(archive),按惯例它们的文件名都以.a结尾。比如,标准C语言函数库/usr/lib/libc.a和X11函数库/usr/X11/lib/libX11.a。
可以容易地创建和维护自己的静态库,只要使用 ar(代表archive,即建立归档文件)程序和gcc -c命令对函数分别进行编译。我们应该尽可能把函数分别保存到不同的源文件中。如果函数需要访问公共数据,我们则把它们放在同一个源文件中并使用在该文件中声明的静态变量。
下面我们来创建一个小型函数库,它包含两个函数,然后在一个示例程序中调用其中一个函数。这两个函数分别是pro1和pro2。按下面步骤生成函数库及测试函数库。
首先,为两个函数分别创建各自的源文件(将它们分别命名为pro1.c和pro2.c)。
$ cat pro1.c
#include <sdtio.h>
void pro1(int arg)
{
printf(“hello:%d\n”,arg)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论