gcc编译
基础学习——gcc编译
编译——就是一个将源代码翻译成计算机处理器能识别的语言的过程。
gcc
gcc是linux系统中通用的c编译器。
举例说明:
test.c
#include <stdio.h>
int main(void){
printf("Hello world\n");
return 0;
}
编译命令如下:
gcc test.c -o test
生成可执行文件test。实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。
1. 预编译(预处理Preprocessing)
预处理功能主要包括 宏定义、文件包含、条件编译 三个部分。
预处理过程读入源码,检查包含预处理指令的语句和宏定义,并对原代码进行相应的转换。预处理过程还会删除程序中的注释和多余的空白字符。
预处理指令 是指 以#开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
gcc -E test.c -o test.i //可以查看test.i,里面存放着test.c经过预处理后的代码
或者
gcc -E test.c //直接在命令行窗口中输出预处理后的代码
指令 用途
# 空指令,无任何效果
#include 包含一个源代码文件
#define 定义宏
#undef 取消已定义的宏
#if 如果给定条件为真,则编译下面代码
#ifdef 如果宏已经定义,则编译下面代码
#ifndef 如果宏没有定义,则编译下面代码
#elif 如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif 结束一个#if……#else条件编译块
#error 停止编译并显示错误信息
#else 略
#error 指令将使编译器显示一条错误信息,然后停止编译。
#line 指令可以改变编译器用来指出警告和错误信息的文件号和行号。
#pragma 指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某 些烦人的警告信息。
应用代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIX 6
#define SEVEN 7
#define Cube(x) (x)*(x)*(x)
#define VERSION "tzs"
#define PASTE(n) "最终胜利者是:"#n
#define NUM(a,b,c) a##b##c // 其中 ##代表连接符,将a,b,c连接在一起
#define STR(a,b,c) a##b##c
#define DEBUG 1
int main()
{
int i;
i = SIX + SEVEN;
printf("i = %d\n",i);
i = (SIX * SEVEN);
printf("i = %d\n",i);
i = Cube(3);
printf("i = %d\n",i);
printf("%s",VERSION);
printf("%s",PASTE(桃子));
puts(PASTE(yy/));
puts(PASTE(xx));
printf("%d\n",NUM(1,2,3));
//printf("%s\n",STR("aa","bb","cc"));
#if DEBUG
printf("Debugging\n");
printf("Debugging2222\n");
#endif
printf("Running\n");
#if defined DEBUG
printf("yes\n");
#endif
#if !defined JJ
printf("no JJ\n");
#endif
}
参考:
http://blog.csdn.net/dotphoenix/article/details/4345174
http://www.cnblogs.com/ligongzi/archive/2012/08/24/2654732.html
2. 编译(Compilation,编译为汇编代码)
预处理之后,可以直接对生成的 test.i 进行编译,生成汇编代码:
gcc -S test.i -o test.s
gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。
3. 汇编
对上面生成的汇编代码test.s,gas汇编器负责将其编译为目标文件。
gcc -c test.s -o test.o
gas汇编器是Linux平台的标准汇编器,它是gcc所依赖的后台汇编工具,通常包含在binutils软件包中。gas使用标准的AT&T汇编语法。
4. 链接
gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。(链接器程序可以实现 编译器的输出 与 编译程序所需要库 之间的链接)
对于上面生成的test.o,将其与C标准输入输出库进行连接,最终生成程序test。
gcc test.o -o test
运行./test即可输出“Hello World!”。
库是预编译的目标文件(object files)的集合,它们可被链接进程序。静态库以后缀为‘.a’的特殊的存档文件(archive file)存储。
标准系统库可在目录 /usr/lib 与 /lib 中找到。比如,在类 Unix 系统中 C 语言的数学库一般存储为文件 /usr/lib/libm.a。该库中函数的原型声明在头文件 /usr/include/math.h 中。
C 标准库本身存储为 /usr/lib/libc.a,它包含 ANSI/ISO C 标准指定的函数,比如‘printf’。对每一个 C 程序来说,libc.a 都默认被链接。
参考:http://www.cnblogs.com/fly1988happy/archive/2012/03/31/2427274.html