在 Linux 环境下学习 C 语言
本文介绍如何在 Linux 平台,以一种“透明”的方式学习 C 语言。
创建个人 root 系统
所谓“个人 root”系统,其实就是避免把软件安装到系统路径。这样我们可以方便的查看 root 目录下的文件,审查所安装软件的具体行为,而不必到系统目录中查找。创建个人 root 系统还可以避免使用系统 root 权限。
创建 root 系统目录:
$ mkdir ~/root # 用于保存非系统程序库
将个人 root 系统目录添加到系统路径:
$ mkdir ~/root # 用于保存非系统程序库
其实,这样的个人路径,在类似 Ubuntu 的系统中已经默认存在了,即个人文件夹下的 .local
目录。如果你愿意,完全可以使用该目录,而且不需要去修改系统路径。
从源码编译程序库
学习 C 语言完全可以像学习 Python 那样,直接使用现成的库。在 C 语言几十年的发展过程中,除了标准库的更新外,还产生了无数质量上乘的第三方库。利用这些库,我们可以更愉快的编程了。
下面会以 GSL 库为例,介绍类似第三方库的安装和使用方法,为后续学习其他的库奠定基础。
$ wget http://mirrors.ustc.edu.cn/gnu/gsl/gsl-2.6.tar.gz
$ tar xvzf gsl-2.6.tar.gz
$ cd gsl-2.6
$ ./configure --prefix=$HOME/root # 使用 prefix 参数指定安装目录
$ make && make install
该程序库将被添加到个人 root 系统,可以去目录中查看具体安装了哪些东西。
构建包含库的 C 程序
编写测试程序:
// 文件名:gsl_erf.c
#include <math.h> // erf, sqrt 等
#include <stdio.h> // printf 等
#include <gsl/gsl_cdf.h>
int main() {
double bottom_tail = gsl_cdf_gaussian_P(-1.96, 1);
printf("Area between [-1.96, 1.96]: %g\n", 1 - 2 * bottom_tail);
}
编写 Makefile
文件,通过 -I
指定库的头文件搜索路径;通过 -L
指定库的搜索路径:
CFLAGS=-I${HOME}/root/include -g -Wall -std=gnu11 -O3
LDLIBS=-L${HOME}/root/lib -lgsl -lgslcblas -lm
或者使用 GSL 自带的配置信息,该命令会自动计算出相关的路径:
CFLAGS=`gsl-config --cflags` -g -Wall -std=gnu11 -O3
LDLIBS=`gsl-config --libs`
编译测试程序:
$ make gsl_erf
运行测试程序:
$ export LD_LIBRARY_PATH=$HOME/root/lib:$LD_LIBRARY_PATH # 指定库路径
$ ./gsl_erf
Area between [-1.96, 1.96]: 0.950004
对于运行时需要连接共享库的程序,和编译过程一样,同样需要指定库的路径,可以通过修改 LD_LIBRARY_PATH
变量实现。
关于 GCC 和 Makefile
Makefile
编译过程的套路一般为:
- 设置编译器选项的变量:
CFLAGS
为我们提供了编译器的一些选项 - 设置连接器选项的变量:
LDLIBS
为我们提供了连接器的一些选项。 - 使用
make
等工具将变量转换成真正的编译和连接的命令
常用编译器选项:
选项 | 说明 |
---|---|
-g | 加入调试符号 |
-Wall | 添加编译器警告 |
-std=gun11 | 编译器版本为 C11 |
-O3 | 优化等级为 3 |
-o | 指定输出的文件名,默认文件名为 a.out |
常用连接器选项:
选项 | 说明 |
---|---|
-I(大写的 i) | 添加头文件搜索路径 |
-L | 添加库文件搜索路径 |
-l(小写的 L) | 指定需要连接的库:-lgsl 自动连接名为 libgsl.a 库 |