编译命令,用来将指定的.c文件编译为对应平台可以运行的程序文件
编译是不是一步到位呢?
并不是
gcc/arm-linux-gcc编译包含四个步骤
编译时是一个文件一个文件编译的
1.预处理(preprocessing)
用来处理代码里面以‘#’开头的行
1.1 #include
预处理的时候,会将包含的.h文件的内容展开(直接复制)到当前的位置
#include <stdio.h>
#include <LinkedQueue.h>
#include 告诉了编译器本文件需要那些头文件
但是文件在哪?
有三个地方
1.环境变量中指定了
头文件搜索路径
比如/usr/include 本地编译头文件路径
/usr/local/arm/arm..... 交叉编译文件夹下的/usr/include/
2. ./ 当前目录
3. 使用编译命令 通过选项 -I指定的路径
gcc main.c -o main -I../inc/
为什么需要头文件?
当1.c文件调用2.c文件的资源时,编译器不知道这些资源存在
只有声明了这些资源存在,编译才能进行下去。
那么一个文件用到2.c资源,在这个文件里面写一遍,十个文件写十遍
一百个呢?如果你已给文件用到上百个文件的资源呢?
所以我们需要一种专门的文件去写声明及类型的定义
第二个用处时 告诉被人你写的东西怎么用
头文件中
#ifndef xxx
#define xxx
#endif
防止头文件的重复包含
"" 与<>的区别
搜索路径的不同
""现在工程本地查找,再到系统的标准路径下查找
<>现在系统的标准路径下查找,再到工程本地查找
标准路径就是环境变量
-I指定的路径
1.2 #define 宏定义
用一个符号去表示一个特定的常量
在预处理,define 是做文本替换!!!
#define A 3+4
A*3 =? =》3+4*3 =》15
宏定义是可带参数
#define MAX(a,b) a>b?a:b
MAX(3,4) => 4
MAX(3<4,4>5) =>? //0
3<4>4>5?3<4:4>5 =>0 =>#define MAX(a,b) (a)>(b)?(a):(b)
在开发的过程中,我们不希望代码里面出现有意义的数字
因为别人看不到这些数字是什么意思 用define 给这些数字一个名字
有些东西可能会经常修改,如果你直接写常量 下次你得整个工程去找
用一个名字去替代这个常量 如#define A 123 下次你只需要修改
这个宏定义就可以了
1.3 条件编译
#if xxx
如果xxx的值为真 就编译这段代码
#endif
#if 0
这段代码不编译
#endif#if xxx
#else
#endif
#ifndef xxx
如果没有定义 xxx 则编译这段代码
#endififdef xxx
如果定义了xxx 则编译这段代码
#endif
2.编译(compiling)
将.c文件编译为 汇编文件.s
gcc -S hello.c(hello.i) -o hello.s
3.汇编(Assermbling)
将汇编文件编译成一个目标文件.o
gcc -c hello.s -o hello.o
4.链接(linked)
将多个目标文件.o链接成一个可执行的程序文件
会将各个.o文件的数据段,整合到一起,并解决地址冲突问题
gcc xxx.o -o main
2.GDB调试工具
gdb是一个单步调试服务,它可以使你的程序在输入控制命令后才运行
并且答应中间变量的值
要使用gdb调试,编译的时候需要加上 -g
gcc -g main.c -o main使用的时候 gbd main
l:list 用于列举代码
b 设置断点 到运行到断点的位置就会停下来
b 行号
info b:查看所有断点的信息delete 断点编号 删除断点
n , s 这都两都是执行下一步
s 如果下一行是一个函数 则进入到函数内部去
n next 会把这个函数执行完
run 运行程序 直到遇到断点或者程序执行完了
c:continue继续运行
start 从main开始运行 但是只运行一部p :printf 可以打印变量的值
display:设置想要跟踪的变量
q:退出
help 获取帮助修改某个变量的值 set var 变量名 = 要设置的值