一.GNU编译器
-
GCC的基本特点
1)支持多种硬件架构
x86-64
Alpha
ARM
Motorola 68000
MIPS
PDP-10/11
PowerPC
System/370-390
SPARC
UAX
2)支持多种操作系统
Unix
Linux
BSD
Mac OS X
iOS
Windows
3)支持多种编程语言
C/C++
objective-C
Java
Fortran
Pascal
Ada
4)查看版本信息
早期:GCC = GNU C Compiler
现代:GCC = GNU Compiler Collection
版本:gcc -v -
构建过程
从源代码到可执行程序的构建过程:
源代码 可执行程序
预编译(编译预处理):头文件扩展,宏扩展
gcc -E hello.c
gcc -E hello.c -o hello.i
汇编:将高级语言代码翻译成汇编语言代码,得到一个汇编语言文件
gcc -S hello.i ——>hello.s
编译:将汇编语言代码翻译成机器语言代码,得到目标模块
gcc -c hello.s ——> hello.o
链接:将所有目标模块及其所依赖的各种库连接成一个整体,得到可执行程序
gcc -hello.o <其他目标木块___> -l<其他库> -o hello
代码:hello1文件夹 -
常见文件名后缀
.h ->C语言代码头文件
.c ->预处理前的C语言源代码文件
.i ->预处理后的C语言源代码文件
.s ->汇编语言文件
.o ->目标模块
.a ->静态库文件
.so ->动态库(共享库)
习惯上可执行程序不带后缀 -
编译选项
gcc [选项] [参数] 文件
gcc -E -o hello.i hello.c
-o:指定输出文件的路径
-E:预编译,缺省输出到屏幕,用-o选项可以指定输出到文件
-S:汇编,将高级语言源文件汇编成汇编语言源文件
-c:编译,将汇编语言源文件编译成机器语言目标模块
-Wall:报告所有警告
代码:wall文件夹
-Werror:将警告视作错误
代码:werror.c
-x:显示指明源代码所用编程语言
代码:cpp.c
-g:产生调试信息
-O0/O1/O2/O3:优化策略,
O0表示不做优化,
O1表示缺省优化策略,在空间和时间上取选择尽可能折中的优化处理
O2表示牺牲空间换取时间(追求快)
O3表示牺牲时间获取时间(追求占用内存小) -
头文件
1)头文件里放什么?
A.头文件卫士
a.h
/
b.h c.h -钻石包含
\ /
d.c
在编译d.c的过程中会对a.h中定义的宏或数据类型等报重定向错
在a.h中加入头文件爱你卫士:
#ifndef A_H
#define A_H
只被编译器处理一次的代码…
#endif //A_H
或
#pragma once
B.包含其他头文件爱你
a.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
b.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
c.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
common.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
....
a.c
#include "common.h"
b.c
#include "common.h"
c.c
#include "common.h"
C.宏定义
geom.h
#defin PAI 3.14159
...
D.自定义类型
geom.h
struct Circle {
double x;
double y;
double r;
}
E.类型别名
types.h
typedef unsigned long long ULL;
typedef int* (*PFOO)(char*, short const*);
...
F.声明外部变量
glable.c
double e = 2.71828
...
glable.h
extern double e;
...
G.声明函数
geom.h
double Circle_area(double r);
...
一个头文件(.h)可能不会被多个源文件(.c)包含,写在头文件里的函数定义
也会因此被预处理器扩展到多个包含该头文件的源文件中
并在编译阶段被编译到多个不同的目标模块中,这将导致链接错误
mutiple definition, 多重定义。因此一般情况下,要避免将函数定义写到头文件中。
a.h
int foo(int a, int b) {return a + b};
-----------------------------------
a.c
int foo(int a, int b) {return a + b};
a.h
int foo(int a, int b);
- 去哪里找头文件呢?
/ 系统目录:/usr/include等目录
头文件位于 -当前目录
\附加目录:通过gcc的-I选项指定
尖括号包含:如:#include <calc.h>
附加目录——>系统目录
双引号包含:如:#include “calc.h”
附近目录——>当前目录——>系统目录
头文件的系统目录:
/usr/include —— 标准库
/usr/loacl/include —— 第三方库
/usr/lib/gcc/i686-linux-gun/<版本号>/include —— 编译器相关库
/usr/include/C++/<版本号> —— 标准C++库
代码:calc/
6.预处理指令
#include:将指定的文件内容插至此指令处
#define:定义宏
#under:删除宏
#if:如果
#ifdef:如果宏已定义
#idndef:如果宏未定义
#else:否则,与#if/#ifdef/#ifndef配合使用
#elif:否则如果,与#if/#ifdef/#ifndef配合使用
#endif:结束判定,与#if/#ifdef/#ifndef配合使用
#error:产生错误,提前终止预处理过程
代码:error/
#warning:产生警告,不会终止预处理过程
代码:error/
#line:显式指定下一行行号
代码:line/
#pragma:设置编译器的状态或者指示编译器的操作
#pragma once ——> 一次性编译
#pragma GCC dependency <被依赖文件> ——> 指定文件依赖
作用:如果被依赖文件比包含该预处理指令的文件新,则产生警告
#pragma GCC posion <语言禁忌>
作用:如果在代码中出现语言禁忌,则产生编译错误
#pragma pack(1/2/4/8—) ——> 字节对齐
代码:once/
- 预定义宏
BASE_FILE :表示正在被编译的文件名
FILE :所在文件的文件名
a.h
BASE_FILE ——> b.c
FILE ——> a.h
b.c
#include “a.h”
gcc -c b.c
LINE :所在行号(受#line影响)
FUNCTION :所在函数的函数名
func :等价于__FUNCTION__
DATE :编译日期
TIME :编译时间
INCLUDE_LEVEL :包含的层数,从0开始
a.h
INCLUDE_LEVEL ——> 2
b.h
INCLUDE_LEVEL ——> 1
#include “a.h”
c.c
INCLUDE_LEVEL ——> 0
#include “b.h”
gcc -c c.c
__cplusplus :C++有定义,C无定义
代码:predef/ - 环境变量
C_INCLUDE_PATH(C_PATH):指定C语言头文件的附加目录,相当于gcc命令的-I选项
CPLUS_INCLUDE_PATH:指定C++语言头文件的附加目录,相当于g++命令的-I选项
LIBRARY_PATH:指定链接时查找库的目录
LD_LIBRARY_PATH:在运行的时候查找动态库的目录
export 环境变量名=环境变量值 \ _____
export 环境变量名=KaTeX parse error: Expected 'EOF', got '#' at position 67: …hrc 定义头文件的三种方式 #̲include "/home/…C_INCLUDE_PATH:/home/tarena/include
export C_PATH=$C_INCLUDE_PATH:/home/tarena/include
同时构建多个项目,容易发生版本冲突
gcc … -I/home/tarena/include
既不需要修改源程序,也不会发生版本冲突,推荐使用此方法
二:静态库和动态库
1.库
big.c ——> big.o ——> big
text.c ——> text.o \ 实现功能 使用功能
image.c ——> image.o | 库 + main.o <—— main.c
video.c ——> vedio.o / \ /
main.c ——> main.o exe
2.静态库
- 静态库本质就是将多个目标文件(.o)打包成为一个文件。链接静态库就是将库中被调用的代码复制到调用模块中
静态库占用空间比较大,库中代码一旦修改,必须重修链接。使用静态库的代码在运行时无需依赖库,且执行效率高 - 静态库的形式:libxxx.a
- 构建静态库
ar -r libxx.a xxx.o yyy.o zzz.o … 把后边所有.o文件房贷.a文件 - 链接静态库
gcc … -lxxx -L<库路径> -o …
gcc … -lxxx … <—— LIBRARY_PATH - 调用静态库:运行时完全不调用静态库中代码。
代码:static/