嵌入式常见面试题——C语言篇

张开发
2026/7/1 21:36:54 15 分钟阅读
嵌入式常见面试题——C语言篇
1、关键字static有什么作用static在不同场景下有不同含义静态局部变量函数内用static修饰的变量仅在首次调用时初始化后续调用保留上次结束时的值生命周期延长至整个程序运行期。静态全局变量全局变量前加static作用域被限制在定义它的源文件内其他文件无法通过extern引用。静态函数用static修饰的函数作用域同样限于定义它的源文件可避免不同文件的函数名冲突。2、volatile关键字的作用是什么在什么场景下使用volatile告诉编译器该变量可能被意外修改禁止编译器对其访问进行优化每次必须从内存中重新读取。三大使用场景硬件寄存器映射寄存器值可能被硬件自行改变如定时器计数寄存器。中断服务程序中修改的变量ISR中修改的全局标志位。多任务共享变量多线程/多任务环境下各任务共享的标志位。典型代码示例cvolatile unsigned int *timer_reg (volatile unsigned int *)0x40000000; unsigned int value *timer_reg; // 每次都从硬件寄存器读取3、const关键字的含义和用法const表示“只读”防止变量被意外修改。常见用法const int a;或int const a;— a是常整型数值不可修改。const int *p;— 指针指向的内容不可变但指针本身可变常量指针。int * const p;— 指针本身不可变但指向的内容可变指针常量。const int * const p;— 指针和指向的内容都不可变。4、局部变量、全局变量、动态申请数据分别存放在哪里局部变量存放在栈区stack函数返回后自动释放。全局变量和静态变量存放在静态区data/bss段。动态申请的数据malloc等存放在堆区heap需手动释放。5、堆和栈的区别是什么比较项栈Stack堆Heap管理方式系统自动分配释放手动分配释放malloc/free空间大小较小通常几KB到几十KB较大受系统可用内存限制存储内容局部变量、函数参数、返回地址动态分配的数据访问速度快慢内存分布连续可能不连续易产生碎片6、什么是栈溢出如何预防栈溢出是指栈中存储的数据超出栈的最大容量覆盖其他数据如函数返回地址导致程序崩溃或异常。常见导致栈溢出的操作在函数内定义过大的局部数组或结构体。函数递归调用过深。函数参数过多或传递大型结构体值传递。预防措施避免定义超大局部变量改用静态变量或动态内存。控制递归深度尽量改用迭代。传递大型数据时使用指针减少栈内存占用。配置合理的栈大小并使用工具监控栈使用情况。7、malloc、calloc、realloc的区别malloc分配指定字节大小的连续内存内容未初始化。calloc分配指定个数和每个元素大小的连续内存并将内存初始化为0。realloc调整已分配内存的大小若原内存后空间不足则重新分配并拷贝数据。常见问题内存泄漏未free、野指针free后未置NULL、重复释放、内存越界。8、sizeof和strlen的区别sizeof是编译时运算符返回变量或类型所占内存的字节数计算时包含末尾的\0。strlen是运行时库函数返回字符串的长度不包含末尾的\0。9、结构体字节对齐是什么为什么需要关注数据在内存中的起始地址必须为特定值通常是数据类型大小的整数倍的整数倍。为什么需要关注现代计算机按字如4字节或8字节访问内存未对齐的数据可能需要多次访问降低性能。部分处理器只能访问对齐数据否则会产生硬件异常。结构体对齐规则基本数据类型对齐值通常等于自身大小结构体对齐值为其成员中最大对齐值成员间可能存在填充字节。10、C程序从源代码到可执行文件经历了哪些步骤预处理 → 编译 → 汇编 → 链接预处理处理#开头的指令宏替换、头文件展开、条件编译、删除注释。编译将预处理后的代码转换为汇编代码进行语法语义分析。汇编将汇编代码转换为机器码生成目标文件.o/.obj。链接将多个目标文件和库文件链接成可执行文件解析符号引用。11、define和const的区别比较项#defineconst处理阶段预处理阶段替换编译阶段生效类型检查无有内存分配不分配内存占代码段分配内存占数据段调试无法调试已被替换可调试12、大端Big-Endian和小端Little-Endian的区别大端数据的高位字节存储在内存的低地址端低位字节存储在内存的高地址端网络协议多使用大端。小端数据的低位字节存储在内存的低地址端高位字节存储在内存的高地址端ARM/x86默认使用小端。检测代码可用union或指针方式读取一个多字节整数的最低地址字节来判断。13、如何用C语言编写死循环两种常用方式while(1) { ... }for(;;) { ... }14、指针和数组名有什么区别数组名是常量指向数组首元素的地址不可被赋值修改。指针是变量可以指向任意地址可以被赋值修改。sizeof(数组名)返回整个数组的大小sizeof(指针)返回指针变量本身的大小如4字节或8字节。15、用宏定义写出求两个数最小值的宏并说明注意事项c#define MIN(a, b) ((a) (b) ? (a) : (b))注意事项参数必须加括号防止运算符优先级问题。整体表达式也需加括号防止在复杂表达式中出错。宏可能导致副作用如MIN(a, b)中a被计算两次。

更多文章