嵌入式大厂面经 6(持续更新中!)
这是一个嵌入式大厂面试题专栏,每天更新高频面试题。专栏将包含题目描述、详细解析、相关知识点扩展以及实际代码示例。内容涵盖操作系统、驱动开发、通信协议等核心领域,并结合实际项目经验进行分析。每道题目都会附带面试官可能的追问方向,帮助大家更好地准备面试!
1. 内存对齐
基本概念
- CPU访问内存时,按照特定字节大小(对齐边界)进行访问
- 提高内存访问效率,但可能造成内存空间浪费
// 内存对齐示例
struct Example1 { // 不优化
char a; // 1字节
double b; // 8字节
int c; // 4字节
}; // 总大小24字节
struct Example2 { // 优化排序
double b; // 8字节
int c; // 4字节
char a; // 1字节
}; // 总大小16字节
// 指定对齐方式
#pragma pack(1) // 1字节对齐
struct Example3 {
char a;
double b;
int c;
}; // 总大小13字节
#pragma pack() // 恢复默认对齐
2. 内存泄漏
定义
- 程序申请的内存空间未被正确释放
- 导致可用内存逐渐减少
常见情况和解决方法
// 1. 常见内存泄漏
void badFunction(void) {
int *p = (int*)malloc(sizeof(int));
return; // 忘记释放内存
}
// 2. 正确的内存管理
void goodFunction(void) {
int *p = (int*)malloc(sizeof(int));
// 使用内存
free(p); // 释放内存
p = NULL; // 避免悬空指针
}
// 3. 智能指针思想(C++)
class SmartPtr {
int* ptr;
public:
SmartPtr(int* p) : ptr(p) {}
~SmartPtr() { delete ptr; }
};
3. 数组名和指针
主要区别
- 本质不同数组名:表示整个数组的起始地址,是常量指针:可变的地址变量
- 内存分配数组:编译时分配连续空间指针:运行时可动态分配
void arrayPointerExample(void) {
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // 指针指向数组首地址
// 数组名不能被修改
// arr = ptr; // 错误:数组名是常量
ptr = arr; // 正确:指针可以修改
// 大小不同
printf("sizeof(arr) = %d\n", sizeof(arr)); // 输出20(5*4字节)
printf("sizeof(ptr) = %d\n", sizeof(ptr)); // 输出4或8(指针大小)
// 数组访问
printf("%d %d\n", arr[0], ptr[0]); // 两种方式等价
printf("%d %d\n", *(arr+1), *(ptr+1)); // 指针运算等价
}
关键注意点
- 数组作为函数参数
// 数组作为参数会退化为指针
void function1(int arr[]) {
// sizeof(arr)此时等于指针大小
}
// 建议使用指针+大小的方式
void function2(int *arr, int size) {
for(int i = 0; i < size; i++) {
// 处理数组元素
}
}
- 二维数组和指针
void twoDimensionExample(void) {
int arr[3][4];
int (*p)[4] = arr; // 数组指针
// 访问方式
arr[1][2] = 10; // 数组方式
*(*(p + 1) + 2) = 10; // 指针方式
}
这些概念在C语言中都非常重要,正确理解和使用它们可以帮助我们写出更高效、更可靠的代码。
更多内容全在下方专栏
全网最受欢迎的嵌入式笔试专栏
笔试专栏包含全部最新的笔试必考考点,非常适合在找工作面经薄弱的同学
3000+订阅还会涨价,提前订阅提前享受,持续更新中。
专栏链接:https://www.nowcoder.com/creation/manager/columnDetail/mPZ4kk