buntu下C编程,编译基础

 
 

C 编程中相关文件后缀

.a 静态库 (archive)
.c C源代码(需要编译预处理)
.h C源代码头文件
.i C源代码(不需编译预处理)
.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.out
hello, ubuntu

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

$ gcc -Wall helloubuntu.c -o helloubuntu

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

$ ./helloubuntu
hello, ubuntu

源文件生成对象文件

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

$ 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”);
}

下面的命令将两个文件分别编译为对象文件且将其链接为可执行程序 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 不能具有指定路径的能力,但是它要求编译器在系统库目录下找寻该库。

创建共享库

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

要构建一个共享库,首先要编译出库中需要的对象模块。例如:下面是文件名为 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,因为库中的函数要在程序运行时被加载。

超越命名惯例

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

$ gcc -xc helloubuntu.jxj -o helloubuntu

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

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

ubuntu下C编程,编译基础( 转)的更多相关文章

  1. ubuntu下使用反编译apk,工具dex2jar和jd-gui

    ubuntu下使用反编译apk, 工具 1:通过apk-tool反编译出资源文件: http://code.google.com/p/android-apktool/ 2.首先使用dex2jar反编译 ...

  2. Ubuntu下使用gcc编译c文件,未识别cos,sin

    Ubuntu下使用gcc编译c文件,虽然我调用了math.h的头文件,但是未识别cos,sin 报错:( fft.c ) /tmp/ccwXjD8C.o: In function `fft': fft ...

  3. ffmpeg2.2在ubuntu下使用NDK编译——并在android工程下测试使用

    作者:wainiwann 出处:http://www.cnblogs.com/wainiwann/ 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  4. Ubuntu 下安装opencv 编译后执行找不到库

    在ubuntu下编译opencv程序后,执行报下面到错误:error while loading shared libraries: libopencv_core.so.2.4: cannot ope ...

  5. 搭建Ubuntu下c/c++编译环境【转】

    1.       安装Ubuntu. 2.       安装gcc 方法一: sudo apt-get  install  build-essential 安装完了可以执行 gcc--version的 ...

  6. ubuntu下串口编程备忘

    弄了一下串口,一个小问题多折腾了下,备忘.软件环境:zl@zhanglong:~$ cat /etc/lsb-release DISTRIB_ID=UbuntuDISTRIB_RELEASE=12.0 ...

  7. (1)Ubuntu下CloudCompare的编译

    Ubuntu下,需要提前安装openGL和Qt 为了可视化操作,使用Cmake进行编译设置 将下载的CloudCompare文件夹下的cmakeList.txt用cmake作为打开方式 Cmake设置 ...

  8. ubuntu下objective-c的编译和运行

    ubuntu 下编译objective-c 1.安装编译环境 sudo aptitude install build-essential gobjc gobjc++ gnustep gnustep-d ...

  9. Ubuntu下math库函数编译时未定义问题的解决

    自己在Ubuntu下练习C程序时,用到了库函数math.h,虽然在源程序中已添加头文件“math.h”,但仍提示所用函数未定义,原本以为是程序出错了,找了好久,这是怎么回事呢? 后来上网查了下,发现是 ...

随机推荐

  1. 日志管理-NLog日志框架简写用法

    本文转载:http://www.blogjava.net/qiyadeng/archive/2013/02/27/395799.html 在.net中也有非常多的日志工具,今天介绍下NLog.NLog ...

  2. java初学者必看经典

    配置java环境变量: JAVA_HOME:配置JDK的目录 CLASSPATH:指定到哪里去找运行时需要用到的类代码(字节码) PATH:指定可执行程序的位置 LINUX系统(在" .ba ...

  3. [Head First Python]1. 初始python-人人都爱列表

    movies = [ "hello", "world",["xin","lover",["Jerry" ...

  4. Android小记之--ClickableSpan

    在给TextView设置超链接时,要想ClickableSpan的onClick事件响应,还必须同时设置tv.setMovementMethod(LinkMovementMethod.getInsta ...

  5. Oracle EBS-SQL (MRP-6):检查MRP计划运行报错原因之超大数据查询1.sql

    /*逐一运行检查计划运行超大数据*/ ---------------------------------------------------- /*查询-1*/ select  plan_id, 'C ...

  6. gl.TexSubImage2D 使用遇到图片翻转的问题

    这2天在用gl.TexSubImage2D把几张小图转拼接成大图,如果在渲染物体之前拼接好就没有问题,但在开始渲染物体后拼接就会有问题.后来我做了2件事情来找原因, 1. 用拼好的图来画一个正方形,大 ...

  7. U盘详解

    摘要:U盘,称呼最早来源于朗科公司生产的一种新型存储设备,名曰“优盘”,使用USB接口进行连接.USB接口就连到电脑的主机后,U盘的资料可与电脑交换.而之后生产的类似技术的设备由于朗科已进行专利注册, ...

  8. mfc subclasswindow attach setwindowlong使用区别

    1. CWnd::Attach BOOL Attach( HWND hWndNew ); 返回值:如果成功,则返回非零值:否则返回0. 参数: hWndNew 指定了Windows窗口的句柄. 说明: ...

  9. 2014.8.15模拟赛【公主的工作】&&bzoj1046[HAOI2007]上升序列

    bzoj题目是这样的 Description 对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm ...

  10. 方差var,标准差

    wiki摘录如下(红色字体是特别标注的部分): 方差:http://zh.wikipedia.org/wiki/%E6%96%B9%E5%B7%AE 方差 变异量(数)(Variance),应用数学里 ...