编译器是把代码编译成机器可以执行的二进制机器码的工具,对于嵌入式设备基本都是需要使用交叉编译工具链。
编译好之后的程序,才可以在目标设备上面运行。
编译器一般分为如下步骤
预编译 —> 编译 —> 链接
拿linux gcc编译器来说
预编译
预编译是解析提供的的程序源码的头文件,并且对于其中的宏进行展开。
对于一套源码我们往往会定义很多宏,如下
#define 定义一个预处理宏
#undef 取消宏的定义
#if 编译预处理中的条件命令,相当于C语法中的if语句
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef 与#ifdef相反,判断某个宏是否未被定义
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
defined 与#if, #elif配合使用,判断某个宏是否被定义
编译器通过解析这些字段可以为后续的编译提供统一的输入环境。
预编译之后的hello_wrold.c 如下图
编译
编译,顾名思义就是把我们人能看懂的代码编译成我们看不懂的二进制代码。
编译器优化:编译时会读取某些关键字,对于有这些关键字修饰的变量会不做优化处理,比如volunteer 。
CPU指令集(二进制)—> 汇编 —>C语言 —>java (计算机语言的发展)
由于计算机只能执行二进制码,所以任何语言都是需要通过编译之后才能在上面执行的。(解析器是另外一套东西,后面可以汇总一下解析器的原理)
gcc编译器可以把所提供的代码编译成汇编语言,汇编语言里各种寄存器的操作移位等。
链接
gcc编译其中有静态编译和动态编译的区别,静态编译会把对应库文件里的代码也拷贝到当前的程序上。
而动态编译则只是把当前的代码编译成二进制码,与所需要的动态模块进行链接。
在运行动态编译的二进制程序时,程序会到系统库亦或者链接库里找对应标记的代码段来运行,静态编译则不需要。
动态编译的优点是节省了空间,而且CPU又是串行的,毕竟像printf这样的代码段谁需要谁加载,用完释放,其乐融融。
给系统动态库添加其他的目录 export LD_LIBRARY_PATH=/opt/au1200_rm/build_tools/bin: $LD_LIBRARY_PATH:
相关指令
gcc -E xx.c -O xx.i #预编译
gcc -S xx.i -o xx.s #编译成汇编
gcc -C xx.s xx.o #编译成二进制
objdump –d xx.o #反汇编
gcc xx.o -o xx.exe #链接
参考文档:https://blog.csdn.net/feng_ge3/article/details/80721059
多谢