01 入门

1.1 Linux程序设计

Linux应用程序有两种文件:

  • 可执行文件:内容为机器代码

  • 脚本文件:由解释器解释执行

四个重要的存放程序的目录:

  • /bin:存放启动系统时用到的程序

  • /usr/bin:存放用户使用的标准程序

  • /usr/local/bin:存放软件安装的程序

  • /opt:可选择操作系统组件或第三方应用可能放在这里

c89:POSIX兼容的标准版本,也是ANSI C标准的第一版。

1.2 头文件

c语言的头文件放在/usr/include及其子目录下。gcc编译器在编译时会自动检索这里的头文件。如果有头文件存放在自定义的位置,如/usr/openwin/include,可以用-I选项包含目录

$ gcc -I/usr/openwin/include hello.c

1.3 库文件

库是一组预先编译好的函数的集合。标准系统库文件一般在/lib/usr/lib下。库文件的名字以lib开头,最后结尾指定库文件的类型

  • .a

    静态函数库,包含在可执行程序中。在运行使用同一个函数库的多个程序时,内存中会有使用的函数的多个副本,且程序文件自身也有多个副本。这造成了内存和磁盘空间的浪费。对应于windows中的.LIB文件。

  • .so

    共享函数库,运行时加载。使用共享库时,程序本身不包含函数代码,而是引用运行时可访问的共享代码。程序执行时,函数引用被解析并产生对共享库的调用,共享库在有必要时才会被加载到内存。内存中只有一份共享库的副本供多个应用程序使用,且在磁盘上也只有一份。共享库还有一个有点是可以独立于应用程序更新。对应于windows中的.DLL文件。

函数库通常同时以静态库和共享函数库的形式存在。用-l加库名的简写形式:下面两条语句,第一条指定了完整路径,第二条会在标准库目下找libm.so或libm.a库(-l优先用共享库)

$ gcc -o hello hello.c /usr/lib/libm.a
$ gcc -o hello hello.c -lm

类似头文件,若库文件在非标准位置,可以用-L选项指定目录。下面的命令用指定目录下的libX11库来编译。

$ gcc -o x11fred x11fred.c -L/usr/openwin/lib -lX11

1.4 编译实例

我们首先创建fred.c和bill.c两个文件

#include<stdio.h>
void fred(int arg)
{
printf("fred: we passed %d\n", arg);
}
#include<stdio.h>
void bill(char *arg)
{
printf("bill: we passed %s\n", arg);
}

用下面的命令生成对象文件(编译但不链接。如果完整编译会报错,因为上面两个文件都没有main函数)bill.o和fred.o

$ gcc -c bill.c fred.c

然后创建头文件lib.h

/*
* This is lib.h It declares the functions fred and bill for users
*/
void fred(int);
void bill(char *);

最后创建应用程序文件

#include<stdlib.h>
#include "lib.h"
int main()
{
bill("Hello World");
exit(0);
}

然后编译program.c,生成program.o。现在我们有文件

  • bill.c

  • bill.o

  • fred.c

  • fred.o

  • program.c

  • program.o

  • lib.h

现在生成最后的可以行文件有两种方式: 一是把应用程序包含使用的函数的对象文件单独链接。

$ gcc -o program program.o bill.o

二是把对象文件归档为一个静态库,再链接。ar是一个归档工具。

$ ar crv libfoo.a bill.o fred.o
$ gcc -o program program.o libfoo.a
$ gcc -o program program.o -L. -lfoo # 也可以用这种加参数的方式