UC 之GNU编译工具GCC

GCC简介

GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器。它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分。GCC原本作为GNU操作系统的官方编译器,现已被大多数类Unix操作系统(如Linux、BSD、Mac OS X等)采纳为标准的编译器,GCC同样适用于微软的Windows。 GCC是自由软件过程发展中的著名例子,由自由软件基金会以GPL协议发布。
GCC 原名为 GNU C 语言编译器(GNU C Compiler),因为它原本只能处理 C语言。GCC 很快地扩展,变得可处理 C++。后来又扩展能够支持更多编程语言,如Fortran、Pascal、Objective-C、Java、Ada、Go以及各类处理器架构上的汇编语言等,所以改名GNU编译器套件(GNU Compiler Collection)

GCC 编译器在编译一个C语言程序时,过程可以细分为四个阶段:
gcc -E : 将C语言源程序预处理,生成.i文件。
gcc -S :预处理后的.i文件编译成为汇编语言,生成.s文件。
gcc -c :将汇编语言文件经过汇编,生成目标文件.o文件。
gcc -o 文件名 :将各个模块的.o文件链接起来生成一个可执行程序文件。-o的作用是指定生成文件的文件名

程序员可以对编译过程进行控制,同时GCC提供了强大的代码优化功能。

gcc -v 查看gcc版本

c程序中的文件后缀名

扩展名说明
.h头文件
.cC源文件
i预处理后的c源文件
.s汇编程序文件
.o目标文件
.a静态链接库
.so动态链接库

gcc 其他常用参数:

参数功能
-o指定输出文件:: gcc a.c -oa.exe(默认为a.out)
-Wall生成尽可能多的警告信息
-Werror要求编译器将警告当做错误处理
-x指定编译代码类型:-x none根据后缀自动识别
-g生成调试信息
-O优化:等级分为O0(不优化)、O1(默认)、O2、O3
-w不生成任何警告信息。
-static禁止使用共享连接。
预处理指令介绍
预编译指示符号说明
#define定义宏或者宏函数
#if、#ifdef、#ifndef、#elif、#else条件编译
#endif结束条件编译
#include将指定的文件插入当前位置
#include_next与include一样,但从当前目录之后的目录查找
#line指定行号
#pragma提供额外信息的标准方法,可用来指定平台
#undef删除宏
#waring创建一个警告
#error产生错误,挂起预处理程序
##连接操作符号,用于宏内连接两个字符串
示例:

错误和警告

#define VERSION 3
#if (VERSION < 2)
#error	"版本过低"
#else 
	#waring "版本高"
#endif

头文件
系统头文件使用:#Include <…> 在系统指定的目录以及I参数目录查找
用户头文件使用:#include “…” 先在当前路径查找后再去系统指定的目录及I参数指定的目录查找。

#pragma
#pragma 有一个等价的宏_Pragma
#pragma GCC poison int 等于 _Pragma("GCC poison int")
#pargma GCC dependency "文件名a ":指定文件a比当前文件新的时候会产生提示警告。
#pargma GCC posion 标识符: 标识符将被定义为毒药,禁止继续使用,否则产生错误。
pragma pack(1) : 可以指定结构的对齐和补齐的字节数。

预定义宏介绍

说明
__BASE_FILE源代码的完整路径
__DATE__日期
__FILE__源代码文件名
__FUNCTION__当前函数名,同(__func__)
__INCLUDE_LEVEL__包含的层数,基本为0
__LINE__行数
__TIME__时间

宏__cplusplus主要解决C/C++混合编程问题,一般用法如下:

#ifdef __cplusplus
extern "C" {
#endif
… //被extern “C”修饰的变量和函数按照C语言方式编译和链接。
#ifdef __cplusplus
}
#endif

修改环境变量
Linux终端中执行export PATH=$PATH:. : 当前窗口有效。
cd ~.bashrc文件末尾加上export PATH=$PATH:. 执行 . .bashrc
编译环境变量
C_INCLUDE_PATH : 查找头文件的目录。c。
CPLUS_INCLUDE_PATH : 查找头文件的目录。C++。
CPATH : 查找头文件,相当于-I选项。与上面重合。
LIBRARY_PATH : 编译时,查找库文件(静态库和共享库),-l选项。
LD_LIBRARY_PATH :运行时定位共享库
程序员自定义头文件的几种查找方法:

  • " "中放入路径的方式:"./test/xx.h"
  • 把目录配置到环境变量CPATH中。
  • gcc -I 头文件目录 进行编译连接。

静态库的创建和使用

  • 编译静态库

    • gcc -c -static test.c-static为可选项,阻止gcc使用共享库。不使用共享库减少运行时间开销,但文件会变大。
    • ar -r libtest.a test.o
      • ar指令 语法:ar [选项] 归档文件名 目标文件列表
    说明
    -d从归档文件删除制定目标文件列表
    -q将指定目标文件快速附加到归档文件末尾。
    -r将指定目标文件插入文档,如存在则更新。
    -t显示目标文件列表
    -x把归档文件展开为目标文件
  • 使用静态库

    • gcc main.c libtest.a
    • gcc main.c -ltest (libtest.a必须在LIBRARY_PATH的指定目录中)
    • gcc main.c -ltest -L(库目录)

共享库的创建和使用

  • 编译共享库
    • gcc -c -fpic test.c gcc -shard test.o -o libtest.so -fpic不写也可以
    • gcc -fpic -shard test.c -o libtest.s
  • 使用共享库与静态库方式一样
    • gcc main.c libtest.so
    • gcc main.c -ltest (libtest.so必须在LIBRARY_PATH的指定目录中)
    • gcc main.c -ltest -L(库目录)

编译时依赖LIBRARY_PATH,但共享库运行时依赖LD_LIBRARY_PATH。
ldd命令可以查看应用程序所使用的共享库
系统提供了一套API可以直接打开共享库:
#include <dlfcn.h>
void * dlopen(const char *filename, int flag);:打开库文件。flag:RTLD_LAZY(符号查找时候才加载),RTLD_NOW(立刻加载)。
void *dlsym(void *handle, const char *symbol); : 从打开的库文件中得到函数
int dlclose(void *handle); : 关闭
char *dlerror(void); : 判断是否出错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值