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. 多行文本垂直居中div高度确定

    父元素高度确定的多行文本.图片.块状元素的垂直居中的方法有两种: 方法一:将内容写入table(包括tbody.tr.td)中的td标签里,同时设置 vertical-align:middle. cs ...

  2. 在controller间分享数据(第一种办法)

    Blood 血腥的方法 每个controller都有自己的scope, 同时也可以共享他们老爸的scope内的数据.如果我们想让两个controller共享数据的化, 有多种方法. 最直接血腥的就是在 ...

  3. Windows上Python3.5安装Scrapy(lxml)

    常用网址: Python 3.5: https://www.python.org/downloads/ Wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlib ...

  4. source install MacPorts--checking for Tcl configuration... configure: error: Can't find Tcl configuration definitions

    If you installed MacPorts using the package installer, skip this section. To install MacPorts from t ...

  5. 自定义View 一 (继承VIew重写onDraw方法)

    项目:具有圆形效果的自定义View 一.继承View并重写onDraw方法 public class CircleView extends View{ private static final int ...

  6. 最少步数(bfs)

    最少步数 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 这有一个迷宫,有0~8行和0~8列: 1,1,1,1,1,1,1,1,1 1,0,0,1,0,0,1,0,1 ...

  7. python 解释器内建函数001

    python解释器内建函数列表如下: 001.abs() 求绝对值 #!/usr/bin/python if __name__=="__main__": print(abs(-10 ...

  8. ui的设计原则

    部分网页设计原则 规划目录结构时应当遵循的几个原则: 1.不要将所有文件都存放在根目录下; 2.按栏目内容分别建立子目录; 3.在每个主目录下都建立独立的images目录; 4.目录的层次不要太深; ...

  9. WindowProc和DefWindowProc的区别

    1. WindowProc是你给自己的窗口定义的窗口处理函数 DefWindowProc是windows平台提供的默认窗口处理函数 如果某些消息你不需要做特别的处理,调用DefWindowProc进行 ...

  10. C#中ref和out的使用小结

    ref传递的参数是变量的地址,在传入函数后,函数可以使用这些地址处的值,同时函数执行完后,这些变量被带回了调用者.ref传递的参数既可作传入值,也可作返回值. out传递的参数是变量的地址,在传入函数 ...