一、编写C程序
可以使用vim也可以使用,vscode
1、 VI 编辑器默认 TAB 键为8 空格,改成4 空格,用vi 打开文件/etc/vim/vimrc,在此文
件最后面输入如下代码:
set ts=4
输入之后按ESC键然后输入:wq
2、VIM编辑器显示行号
VIM 编辑器默认是不显示行号的,不显示行号不利于代码查看,我们设置 VIM 编辑器显示行号,同样是通过在文件/etc/vim/vimrq 中添加代码来实现,在文件最后面加入下面一行代码:
set nu
输入之后按ESC键然后输入:wq
二、编译C程序
使用gcc编译器编译C程序
gcc [选项] [文件名字]
主要选项如下:
-c 只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。
-o <输出文件名> 用来指定编译结束以后的输出文件名,如果使用这个选项的话 GCC 默
认编译出来的可执行文件名字为 a.out。
-g 添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编
译的时候生成调试所需的符号信息。
-O 对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进
行优化,这样产生的可执行文件执行效率就高。
-O2 比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢
三、make工具和makefile文件
当源码文件比较多的时候就不适合通过直接输入 gcc 命令来编译,这时候就需要一个
自动化的编译工具.“
make:一般说GNU Make,是一个软件,用于将源代码文件编译为可执行的二进制文
件,make 工具主要用于完成自动化编译。make 工具编译的时候需要Makefile 文件提供编
译文件。
Makefile:make工具所使用的文件,Makefile 指明了编译规则。·
可以看出我们的代码按照我们所设想的工作了,使用命令“gcc main.c calcu.c input.c -o main
看起来很简单是吧,只需要一行就可以完成编译,但是我们这个工程只有三个文件啊!如果几
千个文件呢? 再就是如果有一个文件被修改了以,使用上面的命令编译的时候所有的文件都会
重新编译,如果工程有几万个文件(Linux 源码就有这么多文件!),想想这几万个文件编译一次
所需要的时间就可怕。最好的办法肯定是哪个文件被修改了,只编译这个被修改的文件即可,
其它没有修改的文件就不需要再次重新编译了,为此我们改变我们的编译方法,如果第一次编
译工程,我们先将工程中的文件都编译一遍,然后后面修改了哪个文件就编译哪个文件,命令
如下: 先将全部.c编译成.o然后再链接起来生成一个可执行文件
gcc -c main.c
gcc -c input.c
gcc -c calcu.c
gcc main.o input.o calcu.o -o main
上述命令前三行分别是将 main.c、input.c 和 calcu.c 编译成对应的.o 文件,所以使用了“-c”选项,“-c”选项是只编译不链接。最后一行命令是将编译出来的所有.o 文件链接成可执行文件 main。假如我们现在修改了 calcu.c 这个文件,只需要将 caclue.c 这一个文件重新编译成.o 文件,然后在将所有的.o 文件链接成可执行文件即,只需要下面两条命令即可:
gcc -c calcu.c
gcc main.o input.o calcu.o -o main
但是这样就又有一个问题,如果修改的文件一多,我自己可能都不记得哪个文件修改过了,
然后忘记编译,然后......,为此我们需要这样一个工具:
1、如果工程没有编译过,那么工程中的所有.c 文件都要被编译并且链接成可执行程序
2、如果工程中只有个别 C 文件被修改了,那么只编译这些被修改的 C 文件即可。
3、如果工程的头文件被修改了,那么我们需要编译所有引用这个头文件的 C 文件,并且
链接成可执行文件。很明显,能够完成这个功能的就是 Makefile 了,在工程目录下创建名为“Makefile”的文件,
文件名一定要叫做“Makefle"区分大小写。
Makefile语法:
规则格式:
目标.....: 依赖文件集合··...·
命令1
命令2
……
比如下面这条规则:
main : main.o input.o calcu.o
gcc:-o main main.o input.o calcu.o
main.o: main.c
gcc -c main .c
input .o: input .c
gcc-c input.c
calcu.o: calcu.c
gcc -c calcu.c
clean:
rm *.o
rm main
main是总的目标,它依赖于main.o input.o calcu.o,而main.o input.o calcu.o却是依赖于main.c……
上述代码中所有行首需要空出来的地方一定要使用“TAB”键!不要使用空格键!这是
Makefile 的语法要求。
makefile写好之后,保存退出,直接输入make就可以执行makefile了
然后用 make clean 清除.o文件
四、makefile基本语法
1、makefile规则格式:
目标.....: 依赖文件集合··...·
命令1
命令2
……
例如:
这条规则的目标是 main,main.o、input.o 和 calcu.o 是生成 main 的依赖文件,如果要更新
目标 main,就必须要先更新它的所有依赖文,如果依赖文件中的任何一个有更新,那么目标也必须更新,“更新”就是执行一遍规则中的命令列表。命令列表中的每条命令必须以 TAB 键开始,不能使用空格!
make 命令会为 Makefile 中的每个以 TAB 开始的命令创建一个 Shel 进程去执行。
上述代码中一共有 5 条规则,1~2 行为第一条规则,3~4 行为第二条规则,5~6 行为第三条
规则,7~8 行为第四条规则,10~12 为第五条规则,make 命令在执行这个 Makefile 的时候其执
行步骤如下:
首先更新第一条规则中的 main,第一条规则的目标成为默认目标,只要默认目标更新了那么就认为 Makefile 的工作,完成了整个 Makefile 就是为了完成这个工作。在第一次编译的时候由于 main 还不存在,因此第一条规则会执行,第一条规则依赖于文件 main.o、input.o 和 calcu.o这个三个.o 文件,这三个.o 文件目前还都没有,因此必须先更新这三个文件。make 会查找以这三个.o 文件为目标的规则并执行。以 main.o 为例,发现更新 ain.o 的是第二条规则,因此会执行第二条规则,第二条规则里面的命令为“gcc -c main.c”,这行命令很熟悉了吧,就是不链接编译 main.c,生成 main.o,其它两个.o 文件同理。最后一个规则目标是 clean,它没有依赖文件,因此会默认为依赖文件都是最新的,所以其对应的命令不会执行,当我们想要执行 clean 的话可以直接使用命令“makeclean”,执行以后就会删除当前目录下所有的.o 文件以及 main,因此clean 的功能就是完成工程的清理,“make clean”的执行过程如下
2、makefile变量
跟 C 语言一样 Makefile 也支持变量的,先看一下前面的例子:
main: main.o input .o calcu.o
gcc -o main main.o input.o calcu.o
上述 Makefile 语句中,main.o input.o 和 calcue.o 这三个依赖文件,我们输入了两遍,我们
这个Makefile 比较小,如果 Makefile 复杂的时候这种重复输入的工作就会非常费时间,而且非
常容易输错,为了解决这个问题,Makefile 加入了变量支持。不像 C 语言中的变量有 int、char
等各种类型,Makefile 中的变量都是字符串!类似 C 语言中的宏。使用变量将上面的代码修改,
修改以后如下所示:
(1)“=”赋值
使用“=”在给变量的赋值的时候,不一定要用已经定义好的值,也可以使用后面定义的值比如如下代码:
加个“@”表示显示命令执行过程。可以看到cumname 的值不是“zzk”,竟然是“zuozhongkai”,也就是变量“name最后一次赋值的结果,这就是赋值符“=”的神奇之处!借助另外一个变量,可以将变量的真实值推到后面去定义。也就是变量的真实值取决于它所引用的套量的最后一次有效值。
(2)“:=”赋值
(3)“?=”赋值
(4)“+=”变量追加
3、makefile模式规则
4、自动化变量
模式规则中,目标和依赖都是一系列的文件,每一次对模式规则进行解析的时候都会是不同的目标和依赖文件,而命令只有一行,如何通过一行命令来从不同的依赖文件中生成对应的目标?自动化变量就是完成这个功能的!所谓自动化变量就是这种变量会把模式中所定义的一系列的文件自动的挨个取出,直至所有的符合模式的文件都取完,自动化变量只应该出现在规则的命令中,常用的自动化变量如表
5、Makefile伪目标
Makefile 有一种特殊的目标一一伪目标,一般的目标名都是要生成的文件,而伪目标不代
表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令
使用伪目标的主要是为了避免 Makefile 中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,有时候我们需要编写一个规则用来执行一些命令,但是这个规则不是用来创建文件的,比如在前面的“示例代码中有如下代码用来完成清理工程的功能:
上述规则中并没有创建文件 clean 的命令,因此工作目录下永远都不会存在文件 clean,当
我们输入“makeclean”以后,后面的“rm*o”和“rmmain”总是会执行。可是如果我们“手贱”,在工作目录下创建一个名为“clean”的文件,那就不一样了,当执行“make clean”的时候,规则因为没有依赖文件,所以目标被认为是最新的,因此后面的 rm 命令也就不会执行,我们预先设想的清理工程的功能也就无法完成。为了避免这个问题,我们可以将 clean 声明为伪目标,声明方式如下
不管有没有文件与这个伪目标重名,这个伪目标都可以去执行。
6、Makefile条件判断
上述用法中都是用来比较“参数 1”和“参数 2”是否相同,如果相同则为真,“参数 1”和“参数2”可以为函数返回值。ifneg 的用法类似,只不过 ifmeg 是用来了比较“参数 1”和“参数 2”是否不相等,如果不相等的话就为真。