Compiling C

来源:互联网 发布:unity3d apk 资源提取 编辑:程序博客网 时间:2024/04/28 05:36

http://wiki.ubuntu.com.cn/index.php?title=Compiling_C&variant=zh-cn

C 编程中相关文件后缀

.a静态库 (archive).cC源代码(需要编译预处理).hC源代码头文件.iC源代码(不需编译预处理).o对象文件.s汇编语言代码.so动态库

[编辑]单个源文件生成可执行程序

下面是一个简单的“hello, ubuntu”程序的源代码:

/* helloubuntu.c */#include <stdio.h>int main(int argc,char *argv[]){printf("hello, ubuntu\n")return 0;}

最简单直接的编译该代码为可执行程序的方法是,将该代码保存为文件 helloubuntu.c,并执行以下命令:

$ gcc -Wall helloubuntu.c 

编译器通过检查命令行中指定的文件的后缀名可识别其为 C 源代码文件。GCC 默认的动作:编译源代码文件生成对象文件(object file),链接对象文件得到可执行程序,删除对象文件。由于命令行中未指定可执行程序的文件名,编译器采用默认的 a.out。在命令行中输入程序名可使其执行并显示结果:

$ ./a.outhello, ubuntu

选项 -o 用来指定所生成的可执行程序的文件名。下面的命令生成名为 helloubuntu 的可执行程序:

$ gcc -Wall helloubuntu.c -o helloubuntu

在命令行中输入程序名将使其执行,如下:

$ ./helloubuntuhello, ubuntu

注意如果有用到math.h库等非gcc默认调用的标准库,请使用 -lm参数

[编辑]源文件生成对象文件

选项 -c 指示 GCC 编译源代码文件,但将对象文件保留在磁盘中并跳过链接对象文件生成可执行文件这一步。在这种情况下,默认的输出文件的文件名同源代码文件名一致,只不过后缀换为 .o 。例如:下面的命令将生成名为 helloubuntu.o 的对象文件:

$ gcc -c -Wall helloubuntu.c

选项 -o 可用来指定生成的对象文件的文件名。以下命令将产生名为kubuntu.o的对象文件:

$ gcc -c -Wall helloubuntu.c -o kubuntu.o

当构建对象库或者生成一系列对象文件以备稍后链接用时,一条命令即可从多个源码文件生成对应的对象文件。下面的命令将生成对象文件ubuntu.o, kubuntu.o 与 xubuntu.o:

$ gcc -c -Wall ubuntu.c kubuntu.c xubuntu.c

[编辑]多个源文件生成可执行程序

即使多个源码文件被编译,GCC编译器也会自动进行链接操作。例如:下面的代码保存在名为 hellomain.c 的文件中并调用一个名为 sayhello()的函数:
/* hellomain.c */void sayhello(void);int main(int argc,char *argv[]){sayhello();return 0;}
以下代码保存在名为 sayhello.c 的文件中并定义了 sayhello() 函数:
/* sayhello.c */#include <stdio.h>void sayhello(){printf("hello, ubuntu\n");/*这里有个小错误,是中文输入法造成的引号使gcc报错*/}

下面的命令将两个文件分别编译为对象文件且将其链接为可执行程序 hello,并删除对象文件:

$ gcc -Wall hellomain.c sayhello.c -o hello

[编辑]编译预处理

选项 -E 指示编译器只进行编译预处理。下面的命令将预处理源码文件 helloubuntu.c 并将结果在标准输出中列出:

$ gcc -E helloubuntu.c

选项 -o 用来将预处理过的代码定向到一个文件。像本文一开始给出的后缀列表所给出的,不需经过预处理的C源码文件保存为后缀为 .i的文件中,这种文件可以这样来获得:

$ gcc -E helloubuntu.c -o helloubuntu.i

[编辑]生成汇编代码

选项 -S 指示编译器生成汇编语言代码然后结束。下面的命令将由 C 源码文件 helloubuntu.c 生成汇编语言文件 helloubuntu.s:

$ gcc -S helloubuntu.c

汇编语言的形式依赖于编译器的目标平台。如果多个源码文件被编译,每个文件将分别产生对应的汇编代码模块。

[编辑]创建静态库

静态库是编译器生成的普通的 .o 文件的集合。链接一个程序时用库中的对象文件还是目录中的对象文件都是一样的。静态库的另一个名字叫归档文件(archive),管理这种归档文件的工具叫 ar 。

要构建一个库,首先要编译出库中需要的对象模块。例如,下面的两个源码文件为 hellofirst.c 和 hellosecond.c:

/* hellofirst.c */#include <stdio.h>void hellofirst(){printf(“The first hello\n”);}
/* hellosecond.c */#include <stdio.h>void hellosecond(){printf(“The second hello\n”);}

这两个源码文件可以用以下命令编译成对象文件:

$ gcc -c -Wall hellofirst.c hellosecond.c

程序 ar 配合参数 -r 可以创建一个新库并将对象文件插入。如果库不存在的话,参数 -r 将创建一个新的,并将对象模块添加(如有必要,通过替换)到归档文件中。下面的命令将创建一个包含本例中两个对象模块的名为 libhello.a 的静态库:

$ ar -r libhello.a hellofirst.o hellosecond.o
现在库已经构建完成可以使用了。下面的程序 twohellos.c 将调用该库中的这两个函数:
/* twohellos.c */void hellofirst(void);void hellosecond(void);int main(int argc,char *argv[]){hellofirst();hellosecond();return 0;}

程序 twohellos 可以通过在命令行中指定库用一条命令来编译和链接,命令如下:

$ gcc -Wall twohellos.c libhello.a -o twohellos

静态库的命名惯例是名字以三个字母 lib 开头并以后缀 .a 结束。所有的系统库都采用这种命名惯例,并且它允许通过 -l(ell) 选项来简写命令行中的库名。下面的命令与先前命令的区别仅在于 gcc 期望的找寻该库的位置不同:

$ gcc -Wall twohellos.c -lhello -o twohellos

指定完整的路径名可使编译器在给定的目录中寻找库。库名可以指定为绝对路径(比如 /usr/worklibs/libhello.a)或者相对与当前目录的路径(比如 ./lib/libhello.a)。 选项 -l 不具有指定路径的能力,但是它要求编译器在系统库目录下找寻该库。 选项-L可以指定具体的目录,使编译器在搜寻系统库目录前先搜寻此目录

$ gcc -Wall -L ./lib/ twohellos.c -lhello -o twohellos

假设libhello.a 在当前目录的lib文件夹下。

[编辑]创建共享库

共享库是编译器以一种特殊的方式生成的对象文件的集合。对象文件模块中所有地址(变量引用或函数调用)都是相对而不是绝对的,这使得共享模块可以在程序的运行过程中被动态地调用和执行。

要构建一个共享库,首先要编译出库中需要的对象模块。例如:下面是文件名为 shellofirst.c 和 shellosecond.c 的两个源码文件:
/* shellofirst.c */#include <stdio.h>void shellofirst(){printf(“The first hello from a shared library\n”);}/* shellosecond.c */#include <stdio.h>void shellosecond(){printf(“The second hello from a shared library\n”);}

要将以上两个源码文件编译成对象文件,可以用下面的命令:

$ gcc -c -Wall -fpic shellofirst.c shellosecond.c

选项 -c 告诉编译器只生成 .o 的对象文件。选项 -fpic 使生成的对象模块采用浮动的(可重定位的)地址。缩微词 pic 代表“位置无关代码”(position independent code)。

下面的 gcc 命令将对象文件构建成一个名为 hello.so 的共享库:

$ gcc -Wall -shared shellofirst.o shellosecond.o -o hello.so

选项 -o 用来为输出文件命名,而文件后缀名 .so 告诉编译器将对象文件链接成一个共享库。通常情况下,链接器定位并使用 main() 函数作为程序的入口,但是本例中输出模块中没有这种入口点,为抑制错误选项 -shared 是必须的。

编译器能将后缀为 .c 的文件识别为 C 语言源代码文件,并知道如何将其编译成为对象文件。基于这一点,先前的两条命令我们可以合并为一条;下面的命令直接将模块编译并存储为共享库:

$ gcc -Wall -fpic -shared shellofirst.c shellosecond.c -o hello.so
下面的程序,存储在文件 stwohellos.c 内,是调用共享库中两个函数的主程序:
/* stwohellos.c */void shellofirst(void);void shellosecond(void);int main(int argc,char *argv[]){shellofirst();shellosecond();return 0;}

该程序可以用下面的命令编译并链接共享库:

$ gcc -Wall stwohellos.c hello.so -o stwohellos

程序 stwohello 已经完成,但要运行它必须让其能定位到共享库 hello.so,因为库中的函数要在程序运行时被加载。 需要注意的是,当前工作目录可能不在共享库的查找路径中,因此需要使用如下的命令行设定环境变量LD_LIBRARY_PATH:

   $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./

[编辑]超越命名惯例

如果环境要求你使用 .c 以外的后缀名来命名你的 C 源码文件,你可以通过 -x 选项来指定其对应的语言以忽略我们的命名规范。例如,下面的命令将从文件 helloubuntu.jxj 编译 C 语言源代码并生成可执行文件 helloubuntu:

$ gcc -xc helloubuntu.jxj -o helloubuntu

通常,在没有 -x 选项的情况下,任何具有未知后缀名的源码文件名都被认为是链接器可以识别的选项,并在不做任何更改的情况下传递给链接器。选项 -x 对其后的所有未知后缀的文件都起作用。例如,下面的命令使 gcc 将 align.zzz 和 types.xxx 都作为 C 源码文件来处理:

$ gcc -c -xc align.zzz types.xxx

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 申请退款后如果不想退了怎么办 世纪明德申请退款但不想退了怎么办 天猫申请换货商家不换怎么办 乐视手机刷机不想清除数据怎么办 捡的苹果手机刷机了要id怎么办 苹果6plus玩王者荣耀卡怎么办 华为荣耀3c的手机内存不足怎么办 红米4x玩王者荣耀卡怎么办 华为手机荣耀10一直重启怎么办 荣耀9青春版老自动重启怎么办 手机开不开机停在华为界面怎么办 华为荣耀9老是反复的重启怎么办 华为荣耀4x老是反复的重启怎么办 手机更新系统后开不了机怎么办 荣耀畅玩7x没有4g网络怎么办 华为4x数字解锁不对中怎么办 华为手机需要解锁后才能刷机怎么办 畅玩6x锁屏壁纸黑了怎么办 指纹密码解锁的手机解不开了怎么办 客户说物流太慢了要退货怎么办 天猫买的手机商家不给发票怎么办 天猫超市下单付款后缺货怎么办 淘宝卖家填写假的单号不发货怎么办 天猫商家72小时未发货怎么办 天猫精灵方糖不按顺序播放怎么办 在天猫购物已付款不发货怎么办 淘宝退货商家收到货不退款怎么办 被有实名认证的闲鱼卖家骗了怎么办 我收到了方正的提示函怎么办 淘宝刷q币单被骗了怎么办 中通快递已签收但是东西丢了怎么办 手机不版本低不支持微信下载怎么办 淘宝虚拟商品不支持7天退货怎么办 卖虚拟物品遇到恶意退款买家怎么办 淘宝极速退款后卖家拒绝退款怎么办 我的天猫积分不让换券了怎么办 微信手机话费充错了怎么办 自己进货在淘宝卖被投诉假货怎么办 京东买的电器售后后服务差怎么办 京东到家申请退款卖家不处理怎么办 天猫买了假货商品下架了怎么办