单一程序:印出 HelloWorld

  • 编辑程序代码,亦即原始码
[root@study ~]# vim hello.c <==用 C 语言写的程序扩展名建议用 .c
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
}

在预设的状态下,如果我们直接以 gcc 编译原始码,并且没有加上任何参数,则执行档的档名会被 自动设定为 a.out 这个文件名!所以妳就能够直接执行 ./a.out 这个执行档啦!那如果我想要产生目标文件 (object file) 来进行其他的动作,而且执行档的档名也不要用 预设的 a.out ,那该如何是好?其实妳可以将上面的第 2 个步骤改成这样:

[root@study ~]# gcc -c hello.c
[root@study ~]# ll hello*
-rw-r--r--. 1 root root 71 Sep 4 11:32 hello.c
-rw-r--r--. 1 root root 1496 Sep 4 11:34 hello.o <==就是被产生的目标文件 [root@study ~]# gcc -o hello hello.o
[root@study ~]# ll hello*
-rwxr-xr-x. 1 root root 8503 Sep 4 11:35 hello <==這就是可執行檔! -o 的結果
-rw-r--r--. 1 root root 71 Sep 4 11:32 hello.c
-rw-r--r--. 1 root root 1496 Sep 4 11:34 hello.o [root@study ~]# ./hello
Hello World

这个步骤主要是利用 hello.o 这个目标文件制作出一个名为 hello 的执行文件,

主、子程序链接:子程序的编译

如果我们在一个主程序里面又呼叫了另一个子程序呢?这是很常见的一个程序写法, 因为可以简化整个程序的易读性!在底下的例子当中,我们以 thanks.c 这个主程序去呼叫 thanks_2.c 这个子程序,写法很简单:


  • 撰写所需要的主、子程序
# 1. 编辑主程序:
[root@study ~]# vim thanks.c
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
thanks_2();
}
# 上面的 thanks_2(); 那一行就是呼叫子程序啦! [root@study ~]# vim thanks_2.c
#include <stdio.h>
void thanks_2(void)
{
printf("Thank you!\n");
}

  • 进行程序的编译与链接 (Link)
# 2. 开始将原始码编译成为可执行的 binary file :
[root@study ~]# gcc -c thanks.c thanks_2.c
[root@study ~]# ll thanks*
-rw-r--r--. 1 root root 75 Sep 4 11:43 thanks_2.c
-rw-r--r--. 1 root root 1496 Sep 4 11:43 thanks_2.o <==编译产生的!
-rw-r--r--. 1 root root 91 Sep 4 11:42 thanks.c
-rw-r--r--. 1 root root 1560 Sep 4 11:43 thanks.o <==编译产生的! [root@study ~]# gcc -o thanks thanks.o thanks_2.o
[root@study ~]# ll thanks*
-rwxr-xr-x. 1 root root 8572 Sep 4 11:44 thanks <==最终结果会产生这玩意儿 # 3. 执行一下这个文件:
[root@study ~]# ./thanks
Hello World
Thank you!

知道为什么要制作出目标文件了吗?由于我们的原始码文件有时并非仅只有一个文件,所以我们无法 直接进行编译。这个时候就需要先产生目标文件,然后再以连结制作成为 binary 可执行文件。另外, 如果有一天,你更新了 thanks_2.c 这个文件的内容,则你只要重新编译 thanks_2.c 来产生新的 thanks_2.o ,然后再以连结制作出新的 binary 可执行文件即可!而不必重新编译其他没有更动过的 原始码文件。

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

[root@study ~]# gcc -O -c thanks.c thanks_2.c <== -O 为产生优化的参数

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

呼叫外部函式库:加入连结的函式库

刚刚我们都仅只是在屏幕上面印出一些字眼而已,如果说要计算数学公式呢?例如我们想要计算出三 角函数里面的 sin (90 度角)。要注意的是,大多数的程序语言都是使用径度而不是一般我们在计算的 『角度』, 180 度角约等于 3.14 径度!嗯!那我们就来写一下这个程序吧!

[root@study ~]# vim sin.c
#include <stdio.h>
#include <math.h>
int main(void)
{
float value;
value = sin ( 3.14 / 2 );
printf("%f\n",value);
}

那要如何编译这支程序呢?我们先直接编译看看:

[root@study ~]# gcc sin.c
# 新的 GCC 会主动将函数抓进来给你用,所以只要加上 include <math.h> 就好了!

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


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

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

  • -l :是『加入某个函式库(library)』的意思,
  • m :则是 libm.so 这个函式库,其中, lib 与扩展名(.a 或 .so)不需要写

所以 -lm 表示使用 libm.so (或 libm.a) 这个函式库的意思~至于那个 -L 后面接的路径呢?这表示: 『我要的函式库 libm.so 请到 /lib 或 /lib64 里面搜寻!』

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

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

-I/path 后面接的路径( Path )就是设定要去搜寻相关的 include 文件的目录。不过,同样的,默认值 是放置在 /usr/include 底下,除非你的 include 文件放置在其他路径。

gcc 的简易用法 (编译、参数与链结)

底下我们就列举 几个 gcc 常见的参数,如此一来大家应该更容易了解原始码的各项功能吧!

# 仅将原始码编译成为目标文件,并不制作链接等功能:
[root@study ~]# gcc -c hello.c
# 会自动的产生 hello.o 这个文件,但是并不会产生 binary 执行档。 # 在编译的时候,依据作业环境给予优化执行速度
[root@study ~]# gcc -O hello.c -c
# 会自动的产生 hello.o 这个文件,并且进行优化喔! # 在进行 binary file 制作时,将连结的函式库与相关的路径填入
[root@study ~]# gcc sin.c -lm -L/lib -I/usr/include
# 这个指令较常下达在最终连结成 binary file 的时候,
# -lm 指的是 libm.so 或 libm.a 这个函式库文件;
# -L 后面接的路径是刚刚上面那个函式库的搜寻目录;
# -I 后面接的是原始码内的 include 文件之所在目录。 # 将编译的结果输出成某个特定档名
[root@study ~]# gcc -o hello hello.c
# -o 后面接的是要输出的 binary file 檔名 # 在编译的时候,输出较多的讯息说明
[root@study ~]# gcc -o hello hello.o -Wall
# 加入 -Wall 之后,程序的编译会变的较为严谨一点,所以警告讯息也会显示出来!

Linux学习-使用传统程序语言进行编译的简单范例的更多相关文章

  1. Linux学习笔记—vim程序编辑器

    vi和vim vim是vi的升级版,支持vi的所有指令 vi的使用 vi分为三种模式:一般模式.编辑模式.命令行模式 一般模式 以vi打开一个文件就直接进入一般模式了,这个模式下可以使用上下左右按键来 ...

  2. [Linux]方便openmp等程序的类似编译

    因为总是打参数例如-fopenmp或者-lGL等等有些麻烦,所以特地写一个可以使用的bash文件用来执行简单的操作 首先在.profile中添加 if [ -d "$HOME/bin&quo ...

  3. Linux环境下用C语言实现socket 通信---简单代码

    Socket编程实例: 服务器端:一直监听本机的8000号端口,如果收到连接请求,将接收请求并接收客户端发来的消息,并向客户端返回消息. 客户端:client.c /* File Name: clie ...

  4. Linux学习总结(十八)几个简单的文本处理工具cut sort tr split

    1 命令cut 用来截取某一个字段格式 : cut -d '分隔符' [-cf] n, n为数字,表示第几段-d:后面跟分隔符,分割符要加单引号-c:后面接的是第几个字符-f:后面接的是第几段那么意思 ...

  5. linux学习书籍推荐《鸟哥的Linux私房菜》下载

    下载地址:点我 <鸟哥的Linux私房菜:基础学习篇>是具有知名度的Linux入门书<鸟哥的Linux私房菜基础学习篇>的最新版,全面而详细地介绍了Linux操作系统.< ...

  6. 简单易懂的程序语言入门小册子(1):基于文本替换的解释器,lambda演算

    最近比较闲,打算整理一下之前学习的关于程序语言的知识.主要的内容其实就是一边设计程序语言一边写解释器实现它.这些知识基本上来自Programming Languages and Lambda Calc ...

  7. linux应用程序设计--GCC程序编译

    GCC程序编译 linux系统下的GCC(GNU C Compiler)是GNU推出的功能强大.性能优越的多平台编译器,是GNU的代表作之一.GCC可以在多种硬件平台上编译出可执行程序,其执行效率与一 ...

  8. Linux C 程序 空语句-gcc编译命令(SIX)

    C语言语句1.空语句:当一个if或者while判断部分能完成工作,空语句可以用来表示if或者while内的空循环体 if(a == b ); 2.gcc编译器 //程序的编译过程: // 预处理:pr ...

  9. Linux学习-核心编译的前处理与核心功能选择

    硬件环境检视与核心功能要求 根据自己的需求来确定编译的选项 保持干净原始码: make mrproper 我们还得要处理一下核心原始码底下的残留文件才行!假设我们是第一次 编译, 但是我们不清楚到底下 ...

随机推荐

  1. TDH-大数据基础

    ------------------------------------------------------------------------------------*******大数据概念和基础* ...

  2. (译)Minimal Shader(最小的着色器)

    (原文:https://en.wikibooks.org/wiki/Cg_Programming/Unity/Minimal_Shader) This tutorial covers the basi ...

  3. ubuntu 14.04 安装minidwep-gtk

    一,安装相关的依赖 sudo apt-get install build-essential libssl-dev iw libpcap-dev sqlite3 libsqlite3-dev libp ...

  4. 【转】HEIF图片存储格式探秘

    HEIF图片存储格式探秘 2017年12月11日 18:30:43 阅读数:891 HEIF,High Efficiency Image File Format,即高效率图档格式,是由动态图像专家组( ...

  5. [opencv bug] orb flannBaseMatcher Exception

    when i use flannBaseMathcer to match 2 sets of orb descriptor, it occured an exception : unsigned lo ...

  6. 字符串(String)杂谈

    作者:臧圩人(zangweiren) 网址:http://zangweiren.javaeye.com >>>转载请注明出处!<<< 上一次我们已经一起回顾了面试题 ...

  7. SQL 字符串函数

    http://www.w3cschool.cn/sql/sql-string-functions.html SQL 字符串函数 序号 Name Description 备注 1 ASCII() 返回最 ...

  8. js操作文档对象的节点

    好吧,为了能让大家不至于睡着,我们先回顾先前面的东东吧~ 1.首先我们写了javaScriput的是一门弱类型的解释性的脚本语言:弱类型:我们的变量不用申明其具体的数据类型,在使用的时候浏览器根据其存 ...

  9. iphone开发思维导图

  10. mininet安装,使用

    http://mininet.org/download/ http://sdnhub.cn/index.php/mininet-walkthrough-chinese/ --------------- ...