嵌入式面经第四弹:兆易创新、联影医疗、诺瓦星云、经纬恒润
本篇涉及的所有问题概要:大家可以试试在看参考答案前,提前尝试解答,以便明确自身知识点的不足部分!
想进大厂做嵌入式?想一次性拿下华为、博世、理想、韶音等20+公司的面试?这份超全嵌入式面经就是你的制胜法宝!
提前模拟来练习这些问题,面试不再慌!
剩下内容都在👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
嵌入式面经第四弹:(嵌入式面经)第11章 20+公司面经杂谈(四):兆易创新、联影医疗、诺瓦星云、经纬恒润
1.说一下局部变量与全局变量的区别。在MCU上空间上有什么不同吗?
2.内联函数和宏函数的区别,你知道吗?
3.进程与线程:区别与应用?
4.数组和链表有什么区别?
5.智能指针是什么,智能指针有哪些?
6.GD32/STM32的启动文件 (startup_stm32xxxx.s)了解吗 ?
7.中断与异常的区别?
8.你在FreeRTOS中如何给任务合理分配栈?
9.简单讲一下整个字符驱动怎么实现的?过程中实现了什么驱动功能?
10.专栏订阅奖励(支持模仿)——个人创新点问答:你机器人小车竞赛中的动态PD差速控制算法是什么,介绍一下设计思想?
---------------------------------------------------------------------------------------------------
1.说一下局部变量与全局变量的区别。在MCU上空间上有什么不同吗?
局部变量(Local Variable)和全局变量(Global Variable)是 两种不同作用域的变量,
它们在存储方式、生命周期、访问权限等方面存在显著区别,
尤其在 MCU(微控制器) 上,由于资源有限,二者的 空间占用 也存在明显不同。
1. 局部变量(Local Variable)
📌 特点
📌 示例
📌MCU 上的存储
- 局部变量默认分配在栈(Stack),函数调用时自动分配空间,函数返回后自动释放。
- 栈空间有限(通常只有几 KB),如果使用过多局部变量,可能导致 栈溢出(Stack Overflow)。
- 局部变量在多次调用时不会保留上次的值(除非使用
static
关键字)。
2. 全局变量(Global Variable)
📌 特点
📌 示例
📌 MCU 上的存储
- 全局变量存放在 RAM 的数据区(BSS 或 DATA 段)。
- BSS 段:未初始化的全局变量(默认初始化为 0)。
- DATA 段:已初始化的全局变量。
- 占用 RAM 的空间固定,如果 RAM 资源紧张,会影响系统性能。
3. 局部变量 vs. 全局变量的空间分布(MCU)
在 MCU(如 STM32)中,RAM 的存储结构一般如下:
📌 空间上的不同点:
- 局部变量存储在栈中,每次函数调用时动态分配,函数返回后释放。
- 全局变量存储在 BSS 或 DATA 段中,始终占据 RAM 空间,不会自动释放。
4. static 变量
static
变量在局部变量和全局变量之间提供了折中方案:
- 局部
static
变量:作用域仍然是局部,但生命周期变成 全局。 - 全局
static
变量:作用域限制在当前文件,不能被其他文件访问(避免变量冲突)。
📌 示例
📌 局部 static
变量存储在 DATA 段,不在栈中,所以不会随着函数调用和返回而释放。
5. 何时使用局部变量 vs. 全局变量
static
修饰局部变量,如果需要长期存储但不想影响全局空间。结论
📌 在 MCU 上,由于 RAM 资源有限,应避免全局变量过多,以免影响系统性能!
🚀 总结:
- 局部变量更节省空间(栈自动管理)。
- 全局变量更占用 RAM(始终驻留)。
- 合理使用
static
,避免全局变量污染。 - MCU 资源有限,应优先使用局部变量,避免栈溢出或 RAM 过度占用!
2.内联函数和宏函数的区别,你知道吗?
在 C 语言和 C++ 中,内联函数(inline) 和 宏函数(#define 宏) 都用于减少函数调用开销,
但它们在实现方式、编译过程、安全性等方面有显著区别。
1. 内联函数(Inline Function)
📌 定义
- 通过
inline
关键字定义的函数,编译时会直接展开到调用处,避免普通函数的调用开销。 - 适用于 短小、频繁调用 的函数,提高执行效率。
📌 示例
📌 运行机制
- 编译时 将
square(5)
替换为5 * 5
,避免了普通函数的 入栈/出栈 开销。 inline
仅是建议,编译器可能忽略,特别是当函数过于复杂时。
📌 优势
✅ 避免普通函数调用开销(如入栈、出栈、参数传递)。
✅ 有类型安全检查(确保参数和返回值匹配)。
✅ 支持调试(能够查看展开后的代码,支持 gdb
调试)。
✅ 适用于 C 和 C++,特别是 C++ 中的类内联函数。
📌 限制
❌ 无法递归调用(编译器不会无限展开)。
❌ 仅适用于短小函数,否则代码膨胀(Code Bloat)。
❌ 编译器可能忽略 inline
关键字,最终仍然按普通函数处理。
2. 宏函数(Macro Function)
📌 定义
- 使用
#define
预处理指令定义的函数,在预处理阶段直接替换。 - 无类型检查,仅仅是文本替换。
📌 示例
⚠️ 如果调用 SQUARE(5+1)
,会被展开为 (5+1 * 5+1)
,结果错误。
📌 运行机制
- 预处理阶段,编译器直接将
SQUARE(5)
替换为(5 * 5)
。 - 不会进行类型检查,也不会在符号表中创建函数。
📌 优势
✅ 无函数调用开销(因为是简单的文本替换)。
✅ 比内联函数更早处理(预处理阶段)。
✅ 适用于简单的数学运算和编译开关(如 #ifdef
)。
📌 限制
❌ 无类型检查,可能导致错误,例如 SQUARE(5+1)
。
❌ 无法调试(无法在 gdb
里设置断点)。
3. 内联函数 vs. 宏函数
4. 适用场景
✅ 适合使用 inline
内联函数
- 短小、逻辑简单的函数,如:
- C++ 类成员函数:
- 需要调试、类型安全 的函数。
❌ 适合使用 #define
宏
- 编译开关
- 简单的数学计算(但要小心副作用)
结论
✅ 推荐使用 inline
代替 #define
宏,因为:
- 更安全(有类型检查)
- 可调试
- 避免
#define
的副作用
❌ 仅在编译开关等场景下使用 #define
宏。
🚀 最佳实践:
- 短小计算函数:用
inline
。 - 编译选项:用
#define
。 - 避免宏副作用,如
#define SQUARE(x) (x*x)
。
🎯 总结:inline
是 #define
宏的安全替代方案,优先使用 inline
,避免 #define
带来的问题!
3.进程与线程:区别与应用?
在操作系统中,进程(Process) 和 线程(Thread) 是并发执行的基本单位,
但它们在资源管理、执行方式、通信方式等方面有显著区别。
1. 进程(Process)
📌 定义
- 进程是程序执行的独立单位,它拥有自己的地址空间,是操作系统进行资源分配和调度的基本单位。
- 每个进程至少包含一个线程(主线程),但也可以包含多个线程(多线程进程)。
📌 特点
📌 示例
🚀 执行 fork()
后,进程会被复制,父进程和子进程拥有独立的地址空间。
2. 线程(Thread)
📌 定义
- 线程是进程的最小执行单元,一个进程可以包含多个线程,这些线程共享相同的地址空间。
- 线程是更轻量级的并发执行单元,能比进程更快地创建和切换。
📌 特点
📌 示例
🚀 pthread_create()
创建的线程与主线程共享数据,可快速切换。
3. 进程 vs 线程:详细对比
4. 进程 vs 线程的应用场景
✅ 使用多进程(Process)
- 独立任务(数据库服务器、浏览器进程)
- 需要高稳定性(避免一个进程崩溃影响其他进程)
- 分布式计算(不同进程运行在不同服务器上)
✅ 使用多线程(Thread)
- 高效并行计算(Web 服务器、多线程下载)
- 共享数据(游戏引擎、图像处理)
- 降低开销(线程切换比进程快)
结论
🚀 进程 提供独立的执行环境,适用于需要隔离的任务。
🚀 线程共享地址空间,适用于需要快速共享数据的任务。