GNU编译器(gcc)

本文详细介绍了GCC编译器的特点、支持的架构和操作系统,以及C/C++编程的构建过程。通过hello.c的例子展示了预编译、编译、汇编和链接的步骤。同时,讲解了头文件的作用、预处理指令的使用,如`#include`、`#define`等,并提到了预定义宏和环境变量的影响。文章还强调了头文件的正确使用和避免重定义错误的方法。
摘要由CSDN通过智能技术生成

1.GCC的基本特点
1)支持多种硬件架构
x86-64
Alpha
ARM
PowerPC
SPARC
VAX
...
2)支持多种操作系统
Unix
Linux
BSD
Android
Mac OS X
iOS
Windows
3)支持多种编程语言
C
C++
Objective-C
Java
Fortran
Pascal
Ada
4)GCC的版本:可以使用gcc -v命令可查

2.构建过程
1、预编译   -E
2、编译       -S
3、汇编       -c
4、链接       -o
源代码(.c)-预编译->头文件和宏扩展(.i)-编译->汇编码(.s)-汇编->目标码(.o)-链接->可执行代码(a.out)

以hello.c的编译过程为例:
vi hello.c - 编写源代码
gcc -E hello.c -o hello.i        预编译(编译预处理)
gcc -S hello.i --->获得汇编代码(hello.s)
gcc -c hello.s ---> 获得目标代码(hello.o)
gcc hello.o -o hello --->获得可执行代码(hello)
./hello - 运行可执行代码

3.文件名后缀
.h - C语言源代码头文件                  \
.c - 预处理前的C语言源代码文件      > 可读文本
.s - 汇编语言文件                            /
.o - 目标文件                                   \
.a - 静态库文件                                 > 不可读的二进制
.so - 共享(动态)库文件                     /
.out - 可执行文件                           /

4.编译选项
gcc [选项] [参数] 文件1 文件2 ...
-o: 指定输出文件
如:gcc hello.c -o hello
-E: 预编译,缺省输出到屏幕,用-o指定输出文件
如:gcc -E hello.c -o hello.i
-S: 编译,将高级语言文件编译成汇编语言文件
如:gcc -S hello.i -o hello.s
-c: 汇编,将汇编语言文件汇编成机器语言文件
如:gcc -c hello.s -o hello.o
-Wall:产生全部警告
如:gcc -Wall wall.c
-Werror:将警告作为错误处理
如:gcc -Werror werror.c
-x: 指定源代码的语言
xxx.c - C语言
xxx.cpp - C++语言
xxx.for - Fortran语言
xxx.java - Java语言
...
如:gcc -x c++ cpp.c -lstdc++ -o cpp
-O0/O1/O2/O3: 指定优化等级,O0不优化,缺省O1优化

5.头文件
1)头文件里写什么?
头文件卫士
#ifndef __XXX_
#define __XXX_
...
#endif
包含其它头文件
宏定义
例如:#define PI 3.14159
自定义类型
例如:struct Circle {
                   double x, y, r;
           };
类型别名
例如:typedef struct Circle C;
外部变量声明
例如:extern double e;
函数声明
例如: int add(int, int); 

注意重定义错误:

一个头文件可能会被多个源文件包含,写在头文件里的函数定义也会因此被预处理器扩展到多个包含该头文件的源文件中,并在编译阶段被编译到等多个不同的目标文件中,这将导致链接错误:multiple definition,多重定义。

2)去哪里找头文件?
gcc -I(大写i)<头文件的附加搜索路径>
例如:#include <my.h>
先找-I指定的目录,再找系统目录。
例如:#include "my.h"
先找-I指定的目录,再找当前目录,最后找系统目录。
头文件的系统目录:
/usr/include - 标准C库
/usr/local/include - 第三方库
/usr/lib/gcc/i686-linux-gnu/5.4.0/include - 编译器库

6.预处理指令
#include - 将指定的文件内容插至此指令处
#define - 定义宏
#undef - 删除宏
#if - 如果
#ifdef - 如果宏已定义
#ifndef - 如果宏未定义
#else - 否则,与#if/#ifdef/#ifndef配合使用
#elif - 否则如果,与#if/#ifdef/#ifndef配合使用
#endif - 结束判定,与#if/#ifdef/#ifndef配合使用
#error - 产生错误,结束预处理
#warning - 产生警告,继续预处理
代码:error.c    gcc -o error error.c -DVER=2
#line - 指定行号
代码:line.c
#pragma - 设定编译器的状态或者指示编译器的操作
#pragma GCC dependency 依赖的文件
文件a依赖于文件b,文件b修改在文件a之前会产生警告
#pragma GCC poison 语法禁忌/如goto    出现goto会产生预处理错误
#pragma pack(按几字节对齐:1/2/4/8)
#pragma pack() - 按缺省字节数对齐,默认4字节

7.预定义宏
无需自行定义,预处理器会根据事先设定好的规则将这些宏扩展成其对应的值。
__BASE_FILE__: 正在被处理的源文件名
__FILE__: 所在文件名
__LINE__: 所在行的行号
__FUNCTION__: 所在函数的函数名
__func__: 同__FUNCTION__
__DATE__: 处理日期
__TIME__: 处理时间
__INCLUDE_LEVEL__: 包含层数,从0开始
a - 0
#include "b" - 1
    #include "c" - 2
__cplusplus: C++有定义,C无定义

8.环境变量
在进程向下文中保存的一些数据:键(功能,是什么)=值(内容)
可用 env命令 查看环境变量    env | grep PATH:查找包含PATH的环境变量
C_INCLUDE_PATH:C语言头文件的附加搜索路径,相当于-I选项
CPATH 等同于 C_INCLUDE_PATH
export  C_INCLUDE_PATH = . 表示添加当前目录到 C_INCLUDE_PATH
CPLUS_INCLUDE_PATH:C++语言头文件的附加搜索路径,相当于-I选项
LIBRARY_PATH:链接库路径
退出终端静态库失效,在~/.bashrc中添加export LIBRARY_PATH=<库路径>,可以使静态库长期有效
LD_LIBRARY_PATH:加载库路径
#include "/.../.../xxx.h"——>这种方式代码移植性较差
#include "xxx.h"
gcc -I/.../... ... —>推荐这种方式
C_INCLUDE_PATH/CPATH=/.../...:/... —>这种方式遇到同名目录情况时容易产生访问冲突

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗里い着迷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值