我们以 Linux 上面最常见的 C 语言来撰写第一支程序!第一支程序最常作的就是….. 在屏幕上面印出“Hello World!”的字样~当然, 这里我们是以简单的 C 语言来撰写,如果你对于 C 有兴趣的话,那么请自行购买相关的书籍喔! ^_^ 好了,不啰唆,立刻编辑第一支程序吧!

Tips 请先确认你的 Linux 系统里面已经安装了 gcc 了喔!如果尚未安装 gcc 的话,请先参考下一节的 RPM 安装法,先安装好 gcc 之后,再回来阅读本章。 如果你已经有网络了,那么直接使用“ yum groupinstall "Development Tools" ” 预先安装好所需的所有软件即可。 rpm 与 yum 均会在下一章介绍。

  • 编辑程序码,亦即源代码

上面是用 C 语言的语法写成的一个程序文件。第一行的那个“ # ”并不是注解喔!如果你担心输入错误, 请到下面的链接下载这个文件:

  1. [root@study ~]# ll hello.c a.out
  2. -rwxr-xr-x. 1 root root 8503 Sep 4 11:33 a.out <==此时会产生这个文件名
  3. -rw-r--r--. 1 root root 71 Sep 4 11:32 hello.c
  4. [root@study ~]# ./a.out
  5. Hello World <==呵呵!成果出现了!

在默认的状态下,如果我们直接以 gcc 编译源代码,并且没有加上任何参数,则可执行文件的文件名会被自动设置为 a.out 这个文件名称! 所以你就能够直接执行 ./a.out 这个可执行文件啦!上面的例子很简单吧!那个 hello.c 就是源代码,而 gcc 就是编译器,至于 a.out 就是编译成功的可执行 binary program 啰! 咦!那如果我想要产生目标文件 (object file) 来进行其他的动作,而且可执行文件的文件名也不要用默认的 a.out ,那该如何是好?其实你可以将上面的第 2 个步骤改成这样:

  1. [root@study ~]# gcc -c hello.c
  2. [root@study ~]# ll hello*
  3. -rw-r--r--. 1 root root 71 Sep 4 11:32 hello.c
  4. -rw-r--r--. 1 root root 1496 Sep 4 11:34 hello.o <==就是被产生的目标文件
  5. [root@study ~]# gcc -o hello hello.o
  6. [root@study ~]# ll hello*
  7. -rw-r--r--. 1 root root 71 Sep 4 11:32 hello.c
  8. -rw-r--r--. 1 root root 1496 Sep 4 11:34 hello.o
  9. [root@study ~]# ./hello

这个步骤主要是利用 hello.o 这个目标文件制作出一个名为 hello 的可执行文件,详细的 gcc 语法我们会在后续章节中继续介绍!通过这个动作后,我们可以得到 hello 及 hello.o 两个文件, 真正可以执行的是 hello 这个 binary program 喔! 或许你会觉得,咦!只要一个动作作出 a.out 就好了,干嘛还要先制作目标文件再做成可执行文件呢? 呵呵!通过下个范例,你就可以知道为什么啦!

  • 撰写所需要的主、副程序
    1. # 1. 编辑主程序:
      [root ~]# vim thanks.c

      include <stdio.h>

      int mainvoid
      {
    2.   thanks_2();
    3. }

      上面的 thanks_2(); 那一行就是调用副程序啦!

[root@study ~]# vim thanks_2.c

include <stdio.h>

void thanks_2(void)
{
printf("Thank you!\n");
}

上面这两个文件你可以到下面下载:

  1. # 2\. 开始将源代码编译成为可执行的 binary file :
  2. [root@study ~]# gcc -c thanks.c thanks_2.c
  3. [root@study ~]# ll thanks*
  4. -rw-r--r--. 1 root root 75 Sep 4 11:43 thanks_2.c
  5. -rw-r--r--. 1 root root 1496 Sep 4 11:43 thanks_2.o <==编译产生的!
  6. -rw-r--r--. 1 root root 91 Sep 4 11:42 thanks.c
  7. -rw-r--r--. 1 root root 1560 Sep 4 11:43 thanks.o <==编译产生的!
  8. [root@study ~]# gcc -o thanks thanks.o thanks_2.o
  9. [root@study ~]# ll thanks*
  10. -rwxr-xr-x. 1 root root 8572 Sep 4 11:44 thanks <==最终结果会产生这玩意儿
  11. [root@study ~]# ./thanks
  12. Hello World
  13. Thank you!

知道为什么要制作出目标文件了吗?由于我们的源代码文件有时并非仅只有一个文件,所以我们无法直接进行编译。 这个时候就需要先产生目标文件,然后再以链接制作成为 binary 可可执行文件。另外,如果有一天,你更新了 thanks_2.c 这个文件的内容,则你只要重新编译 thanks_2.c 来产生新的 thanks_2.o ,然后再以链接制作出新的 binary 可可执行文件即可!而不必重新编译其他没有更动过的源代码文件。 这对于软件开发者来说,是一个很重要的功能,因为有时候要将偌大的源代码全部编译完成,会花很长的一段时间呢!

此外,如果你想要让程序在执行的时候具有比较好的性能,或者是其他的除错功能时, 可以在编译的过程里面加入适当的参数,例如下面的例子:

  1. [root@study ~]# gcc -O -c thanks.c thanks_2.c <== -O 为产生最优化的参数
  2. [root@study ~]# gcc -Wall -c thanks.c thanks_2.c
  3. thanks.c: In function main’:
  4. thanks.c:5:9: warning: implicit declaration of function thanks_2 [-Wimplicit-function-declaration]
  5. thanks_2();
  6. ^
  7. thanks.c:6:1: warning: control reaches end of non-void function [-Wreturn-type]
  8. }
  9. ^
  10. # -Wall 为产生更详细的编译过程信息。上面的讯息为警告讯息 (warning) 所以不用理会也没有关系!

至于更多的 gcc 额外参数功能,就得要 man gcc 啰~呵呵!可多的跟天书一样~

上面这个文件的内容可以在下面取得!


  • 那要如何编译这支程序呢?我们先直接编译看看:
  1. [root@study ~]# gcc sin.c
  2. # 新的 GCC 会主动将函数抓进来给你用,所以只要加上 include <math.h> 就好了!

新版的 GCC 会主动帮你将所需要的函数库抓进来编译,所以不会出现怪异的错误讯息! 事实上,数学函数库使用的是 libm.so 这个函数库,你最好在编译的时候将这个函数库纳进去比较好~另外要注意, 这个函数库放置的地方是系统默认会去找的 /lib, /lib64 ,所以你无须使用下面的 -L 去加入搜寻的目录! 而 libm.so 在编译的写法上,使用的是 -lm (lib 简写为 l 喔!) 喔!因此就变成:

  • 编译时加入额外函数库链接的方式:
    1. [root@study ~]# gcc sin.c -lm -L/lib -L/lib64 <==重点在 -lm
    2. [root ~]# ./a.out <==尝试执行新文件!

特别注意,使用 gcc 编译时所加入的那个 -lm 是有意义的,他可以拆开成两部份来看:

  • -l :是“加入某个函数库(library)”的意思,
  • m :则是 libm.so 这个函数库,其中, lib 与扩展名(.a 或 .so)不需要写
    所以 -lm 表示使用 libm.so (或 libm.a) 这个函数库的意思~至于那个 -L 后面接的路径呢?这表示: “我要的函数库 libm.so 请到 /lib 或 /lib64 里面搜寻!”

上面的说明很清楚了吧!不过,要注意的是,由于 Linux 默认是将函数库放置在 /lib 与 /lib64 当中,所以你没有写 -L/lib 与 -L/lib64 也没有关系的!不过,万一哪天你使用的函数库并非放置在这两个目录下,那么 -L/path 就很重要了!否则会找不到函数库喔!

除了链接的函数库之外,你或许已经发现一个奇怪的地方,那就是在我们的 sin.c 当中第一行“ #include <stdio.h>”,这行说的是要将一些定义数据由 stdio.h 这个文件读入,这包括 printf 的相关设置。这个文件其实是放置在 /usr/include/stdio.h 的!那么万一这个文件并非放置在这里呢?那么我们就可以使用下面的方式来定义出要读取的 include 文件放置的目录:

  1. [root@study ~]# gcc sin.c -lm -I/usr/include

-I/path 后面接的路径( Path )就是设置要去搜寻相关的 include 文件的目录啦!不过,同样的,默认值是放置在 /usr/include 下面,除非你的 include 文件放置在其他路径,否则也可以略过这个项目!

通过上面的几个小范例,你应该对于 gcc 以及源代码有一定程度的认识了,再接下来,我们来稍微整理一下 gcc 的简易使用方法吧!

前面说过, gcc 为 Linux 上面最标准的编译器,这个 gcc 是由 GNU 计划所维护的,有兴趣的朋友请自行前往参考。既然 gcc 对于 Linux 上的 Open source 是这么样的重要,所以下面我们就列举几个 gcc 常见的参数,如此一来大家应该更容易了解源代码的各项功能吧!