千家信息网

嵌入式之 C 语言编译器(五)

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,我们在嵌入式的开发中经常会见到 GCC 和 gcc,那么它们两有何不同呢?GCC(GNU Compile Collection) 是指 GNU 编译器集合,包含众多语言的编译器,如 C、C++、Jav
千家信息网最后更新 2026年11月03日嵌入式之 C 语言编译器(五)

我们在嵌入式的开发中经常会见到 GCC 和 gcc,那么它们两有何不同呢?GCC(GNU Compile Collection) 是指 GNU 编译器集合,包含众多语言的编译器,如 C、C++、Java、D、Objective-C 等;而 gcc 则是特指 GCC 中的 C 语言编译器。那么 GCC 与嵌入式的关系是怎样的呢?多数嵌入式操作系统都是基于 GCC 进行源码编译,如 Linux、VxWorks 以及 Android 等。在实际的开发中,内核相关的开发用的是 gcc,而应用开发用的是 gcc/g++/gdc 等。

下来我们来看看一个嵌入式开发中的高端大气上档次的词语:交叉编译。那么为什么会有交叉编译呢?在以往的嵌入式设备往往都是资源受限的,不可能直接在嵌入式上直接对处理器进行编程。那么此时的解决方案便是在开发主机(PC)上对源码进行编译,最终生成目标主机(嵌入式设备)的可执行程序。gcc 是如何进行交叉编译的呢?1、配置目标主机的编译工具链(如arm-linux);2、配置工具链的具体版本:根据具体的目标代码选择相应的工具链版本,正确使用关于硬件体系的特殊编译选项。下来我们来看看大型企业的嵌入式开发环境是怎样的,如下

这个服务器集群相当于是我们自己公司的内部服务器,版本控制则是指由原来的版本经过我们一些代码的修改之后产生的新版本,用于各个版本的控制的。文件追踪则是指在服务器上面可以看到那部分的代码是具体由哪个人进行改写的,可具体到文件以及部分代码。我们来看看编译器是怎样的,如下

编译器其实是由预处理期、编译器、汇编器以及链接器构成的。我们平时所说的由哪个编译器编译生成的文件,此时的编译器便是指广范围的编译器。那么狭义上的编译器则是指我们在平时所听到的生产一个某语言的编译器,此时的编译器则是指将具体的语言翻译成目标平台代码而已。我们来看看一个 .c 文件是怎样编译成 .o 文件的,具体步骤如下所示

我们看到并不是我们所想象的直接一步就由 .c 文件直接编译成为 .o 可执行文件了,而是经过那么多的步骤才会生成最终的可执行程序的。那么此时便扩展一个问题,我们是如何理解"多语言混合开发"?我们在平时可能会听到多语言混合开发,是指由好几种语言混合进行一个应用程序开发的。那么为什么会产生这种混合的开发方式呢?比如说一个项目是由 C++ 完成的,但是其中的某些部分是可以通过 C# 完成的,此时精通 C++ 的人很少(相应工资就要的很高了),而 C# 的工程师由一大堆,我们就可以需要两个精通 C++ 的工程师和好几个 C# 的工程师来共同完成这个项目,达到以最小的开支完成此项目的效果。或者是你们小组内每个人擅长的语言方向不一样,为了发挥每个人的最大效率便可以采取这种混合开发的方式。下来我们来看看几种多语言混合开发的方式

方式一,如下

此方式是通过由几种语言经过汇编得到目标平台的汇编语言,再由目标平台汇编器统一链接生成可执行程序。行业典型的案例就是 .net framework,它便是由 C#、C++ 以及 VB 混合开发得到的,如下


方式二,如下

它是由各自的语言生成相应的库再通过目标平台链接器统一链接为可执行程序。典型的案例便是 QQ 了,如下

方式三,如下

它是经过各自的编译器先生成可执行程序 .exe,再通过进程间通信协议进而生成可执行程序。行业案例:Eclipse,如下

下来我们来看看 gcc 关键编译选项。

gcc 关键编译选项一:a> 预处理指令是:gcc -E file.c -o file.i;b > 编译指令:gcc -S file.i -o file.s;c> 汇编指令:gcc -c file.s -o file.o。

下来我们来看看效果分别是怎样的


func.h 源码

#include void func(){#ifdef TEST    printf("TEST = %s\n", TEST);#endif    return;}


test.c 源码

#include #include "func.h"int g_global = 0;int g_test = 1;int main(int argc, char *argv[]){    func();        printf("&g_global = %p\n", &g_global);    printf("&g_test = %p\n", &g_test);    printf("&func = %p\n", &func);    printf("&main = %p\n", &main);        return 0;}

我们来看看预处理的效果,打开 test.i 文件看看,开头是这样的

第一行的 1 表示下面的内容是属于 test.c 文件的内容,下面是一些头文件的包含。

# 2 "test.c" 2 的意思是 test.c 头文件的包含已经结束了,# 1 "func.h" 1 表示 func.h 相关内容的开始。最后便是 test.c 文件 main 函数的内容了。下面看看编译指令生成的 .s 文件

都是一些生成的汇编命令。下面来看看最后的汇编指令生成 .o 文件

gcc 关键编译选项二:a> 生成映射文件:gcc -WI,-Map=test.map file.c;b> 宏定义:gcc -D'TEST="test"' file.c;c> 获取系统头文件路径:gcc -v file.c。

gcc 关键编译选项三:生成依赖关系。a> 获取目标完整的依赖关系:gcc -M test.c;b> 获取目标的部分依赖关系:gcc -MM test.c。

下来我们来看看 -M 和 -MM 的效果分别是怎样的,如下

我们看到包含了那么多的头文件,它的格式类似于 makefile 中的目标与依赖的关系。其中依赖是 test.c 和众多的头文件以及我们自己包含的 func.h 头文件。再来看看 -MM 的效果

我们看到 -MM 的效果是指依赖于 test.c 和 func.h,并没有那些别的头文件。

gcc 关键编译选项四:指定库文件及库文件搜索路径。-L 选项是指定库文件的搜索路径;-l 是指定库文件,如 gcc test.c -L -lfunc。


func.c 源码

#include void func(){#ifdef TEST    printf("TEST = %s\n", TEST);#endif    return;}


test.c 源码

#include int g_global = 0;int g_test = 1;int main(int argc, char *argv[]){    func();        printf("&g_global = %p\n", &g_global);    printf("&g_test = %p\n", &g_test);    printf("&func = %p\n", &func);    printf("&main = %p\n", &main);        return 0;}

编译结果如下

我们看到经过 ar crs 命令将 func.o 打包成 libfunc.a 文件后,再通过 gcc test.c -L. -lfunc 命令生成可执行程序 a.out(其中 -L 后面的点代表在当前目录下)。

编译 文件 开发 编译器 生成 目标 语言 嵌入式 程序 方式 混合 效果 源码 代码 关键 指令 版本 C++ 内容 平台 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广东万易互联网科技有限公司惠州分公司 南京欣网互联网络科技有限公司 疫情对互联网科技公司影响 广州宏创互联网科技 互联网女皇 腾讯科技 成都仁贤领冠互联网科技有限公司 富国互联网科技创新基金 天速互联网络科技有限公司 中国科技互联网公司收入 浙南科技城互联网大厦建设工程 华夏恒生互联网科技013171 内蒙古九一互联网科技 南博望互联网科技有限公司 恒生互联网科技业指数调整周期 山东有哪些互联网科技公司 科技互联网的核心竞争力 上海京穆互联网科技有限公司 易企秀互联网科技是做什么的 求路客互联网科技电话 唐山双旺合互联网科技产业园 互联网时代科技改变生活 受益于互联网科技的高速发展 世界互联网科技公司市值排名 如何创新互联网科技 南博望互联网科技有限公司 深圳互联网科技的发展 互联网营销推广黑科技 下一代互联网重大应用科技园 互联网科技机房 平安好医生打造互联网科技医疗
0