嵌入式C面试题 Top 40+ 问答

2025年7月23日 | 阅读14分钟

1) 什么是嵌入式C?/你如何理解嵌入式C语言?

嵌入式C是C语言在C标准委员会指定的语言扩展集。它通常用于解决不同嵌入式系统C语言扩展之间存在的共性问题。嵌入式C编程通常需要C语言的非标准扩展来支持增强的微处理器特性,例如定点算术、多个独立的内存库以及基本的I/O操作。


2) 你如何理解嵌入式系统?

嵌入式系统是一种基于微处理器的计算机硬件系统和软件,它被设计用来执行特定的功能。嵌入式系统要么是一个独立的系统,要么是大系统的一部分。


3) C和嵌入式C之间的主要区别是什么?

C是一种通用、高级编程语言,用于设计任何桌面应用程序。另一方面,嵌入式C是C语言的扩展,用于开发基于微控制器的应用程序。这里的“嵌入式”指的是托管计算机或微控制器,而不是编程语言。让我们在下表中看看C和嵌入式C之间的主要区别。

C与嵌入式C的区别

C 语言嵌入式 C
C是一种通用编程语言,用于设计任何桌面应用程序。嵌入式C只是C编程语言的扩展,用于开发基于微控制器的应用程序。
C是一种高级编程语言。嵌入式C是C编程语言的扩展。
C编程语言是一种与硬件无关的语言。嵌入式C是一种完全依赖于硬件的语言。
C是一种简单的语言,易于阅读和修改。嵌入式C相对复杂,不易阅读和修改。
C编程语言的编译器依赖于操作系统。嵌入式C的编译器独立于操作系统。
在C编程语言中,使用标准编译器来编译和执行程序。在嵌入式C语言中,使用能够生成特定硬件/微控制器输出的特定编译器来编译代码。
一些用于执行C语言程序的流行编译器是
GCC(GNU编译器集合)
Borland Turbo C
Intel C++
一些用于执行嵌入式C语言程序的流行编译器是
Keil编译器
BiPOM ELECTRONIC
Green Hill软件
C编程语言具有自由格式的程序编码。在嵌入式C语言中,格式取决于应用程序中使用的微处理器类型。
C语言程序中的错误修复很容易。嵌入式C语言程序中的错误修复很复杂。
C语言在应用程序中也支持其他各种编程语言。嵌入式C语言仅支持应用程序所需的处理器,而不支持编程语言。
C编程语言需要操作系统。嵌入式C可能需要也可能不需要操作系统。
在C编程语言中,我们可以在程序运行时输入数据。在嵌入式C语言中,我们只能向运行的程序提供预定义输入。
C编程语言支持常规优化。嵌入式C支持高级优化。
C编程语言通常使用台式PC的资源,如内存、操作系统等。嵌入式C语言必须使用有限的资源,例如嵌入式处理器上的RAM、ROM、I/O。
C程序应用程序的一些示例
逻辑程序
系统软件程序等。
嵌入式C程序应用程序的一些示例
DVD
电视
数码相机等。

4) 嵌入式C是编程语言吗?

嵌入式C不是核心编程语言。它是C编程语言的扩展,用于开发基于微控制器的应用程序。嵌入式C语言与普通C编程语言相比引入的扩展包括I/O硬件寻址、定点算术运算、访问地址空间等。


5) 嵌入式C的主要优点是什么?

嵌入式C是C编程语言的扩展。让我们看看嵌入式C的主要优点

嵌入式C的主要优点

  • 嵌入式C的编码速度快,简单易懂。
  • 它不需要任何硬件更改,例如额外的内存或存储空间,因为它始终执行相同的任务。
  • 它专用于特定任务,一次只执行一项任务。
  • 它主要用于现代自动化应用程序。嵌入式应用程序非常适合工业用途。

6) 嵌入式C的主要缺点是什么?

嵌入式C的缺点

  • 嵌入式C一次只能执行一项任务,因此当需要同时执行多项任务时,不建议使用它。
  • 嵌入式C仅支持硬件系统。因此,如果要更改程序,则必须更改硬件。
  • 嵌入式C也存在一些可伸缩性问题,因此,当范围变化或需求变化时,它不能轻易地进行扩展。
  • 它存在一些限制,例如内存或计算机兼容性有限。

7) 嵌入式C中的`volatile`关键字是什么?它的用法是什么?

在嵌入式C中,`volatile`关键字是一种类型限定符,可以防止编译器对对象进行优化。根据C标准,我们可以以实现未知的方式修改`volatile`限定的类型对象。换句话说,我们可以说`volatile`限定对象的值可以随时更改,而无需更改代码。如果`volatile`限定了一个对象,编译器将在每次程序访问该对象时从内存中重新加载其值。从内存中读取值是检查该值不可预测变化的唯一方法。

`volatile`关键字主要用于直接处理GPIO、中断或标志寄存器。它还与线程之间共享的全局变量或缓冲区一起使用。


8) C中的分段错误是什么?分段错误的一些常见原因是什么?

分段错误是一种运行时错误,当程序运行时可能由于某些原因而发生。

以下是C中分段错误的一些常见原因列表

  • 解引用指针的使用:如果我们使用一个可能没有有效地址/内存位置的指针,则可能导致分段错误。
  • 如果您尝试访问只读内存区域,程序可能会返回分段错误。
  • 当您尝试释放(使用指针)已释放的内存时,也可能发生分段错误。
  • 分段错误发生是导致C中堆栈溢出错误的原因。

9) ISR在嵌入式C中的全称是什么?

在嵌入式C中,ISR代表中断服务例程(Interrupt Service Routines)。这些过程存储在特定的内存地址,并在发生某种类型的中断时被调用。


10) C中的堆栈溢出错误是什么?

在C语言中,如果程序尝试访问超出其可用最大限制的内存,则可能发生堆栈溢出错误。例如,如果指针超出了堆栈限制(边界),则可能发生堆栈溢出错误。

当发生堆栈溢出错误时,程序终止,不会执行后续指令。因此,在使用指针和限制边界时必须非常小心。


11) 是否可以从ISR传递任何参数并返回值?

不可以。无法从ISR传递任何参数并返回值。ISR不返回任何内容,也不允许传递任何参数。ISR在硬件或软件事件发生时被调用,代码不会调用它。因此,不会将参数传递给ISR。由于代码不调用ISR,因此没有调用代码来读取ISR的返回值。因此,ISR不返回任何值。


12) 你如何理解中断延迟?

中断延迟是处理器响应中断请求所花费的时钟周期数。这个时钟周期数是从中断请求断言到中断处理器的第一条指令之间的计数。

Cortex-M处理器系列的中断延迟

Cortex-M处理器具有非常低的中断延迟。下表显示了具有零等待状态内存系统的Cortex-M处理器的中断延迟。

处理器零等待状态内存的周期数
Cortex-M016
Cortex-M0+15
Cortex-M312
Cortex-M412
Cortex-M712

13) 如何在嵌入式C中测量中断延迟?

在嵌入式C中,我们可以借助示波器测量中断延迟。请按照以下步骤操作

  • 首先,取两个GPIO。配置一个GPIO以生成中断,第二个GPIO用于切换(您也可以连接LED)。
  • 使用示波器或分析仪监视已配置为生成中断的引脚。
  • 现在,使用示波器或分析仪监视在中断服务例程开始时切换的第二个引脚。
  • 当您生成中断时,两个GPIO的信号都会改变。
  • 现在,您可以轻松读取仪器在两个信号(中断延迟)之间的间隔。

14) 如何减小中断延迟?

有几种方法可以减少嵌入式C中的中断延迟。中断延迟取决于许多因素。以下是其中一些因素的列表

  • 平台和中断控制器
  • CPU时钟速度
  • 定时器频率
  • 缓存配置
  • 应用程序等。

因此,我们可以通过正确选择平台和处理器来轻松减少中断延迟。我们还可以通过缩短ISR来减少中断延迟,并避免在ISR中调用函数。


15) C中的静态变量是什么?为什么我们在C中使用静态变量?

静态变量具有即使超出作用域也能保持其值的属性。这意味着我们只能初始化静态变量一次。它的作用域是局部的,但它一直存在到程序结束。编译器会一直保留该变量直到程序结束。我们可以在函数内部或外部定义静态变量。静态变量的默认值为零。静态变量在程序执行期间一直存在。

C语言中静态变量的语法

静态变量通常用于计数。例如,每当在银行开设新账户时,都会调用函数`openBakAccount()`。然后,为了计算开设账户的总数,我们可以在函数中声明一个静态变量,并在每次函数调用时将其增加。


16) 关于C中的静态变量,有哪些有趣的事实?

以下是C中静态变量的一些有趣事实列表

  • 有两种类型的静态变量:静态int变量和静态auto变量。静态int变量在程序运行时保留在内存中,而普通或auto变量在声明的函数调用结束后被销毁。例如,我们可以使用静态int变量来计算函数被调用的次数,但不能使用auto变量来实现此目的。
  • 静态变量分配在数据段而不是堆栈段的内存中。
  • 静态变量的默认值为0。与全局变量一样,如果未显式初始化,则它们初始化为0。
  • 在C语言中,我们只能使用常量字面量来初始化静态变量。
  • C++中也可能存在静态全局变量和函数。它们主要用于将变量或函数的作用域限制在文件中。
  • 我们不应在结构内部声明静态变量,因为C编译器要求将整个结构元素放在一起。

17) 如何使用另一个源文件中定义的变量?

我们可以使用“extern”关键字来声明一个变量,该变量允许在另一个文件中访问该变量。这就是我们如何使用在另一个源文件中定义的变量。


18) 如何通过指针地址的一些意外修改来保护字符指针?

我们可以使用常量字符指针(`const char*`)来保护字符指针免受意外修改指针地址。它防止对字符串中的指针地址进行不必要的修改。


19) CISC和RISC之间的主要区别是什么?

RISC和CISC之间有许多区别。其中一些如下

RISCCISC
RISC代表精简指令集计算机。CISC代表复杂指令集计算机。
RISC不包含内存单元。CISC包含内存单元。
就计算而言,RISC是比CISC快得多的处理器。就计算而言,CISC是比RISC慢得多的处理器。
RISC用于确保操作的简单解码。CISC不确保简单的操作解码。
RISC的执行时间很短。CISC的执行时间很长。

20) 你如何理解函数指针?

函数指针是指向函数而不是变量的指针。因此,函数指针与类指针完全不同。函数指针存储特定函数的地址,以便相关程序可以通过函数调用来利用它。


21) C中的变量可以同时是常量和易失性吗?

是的,C中的变量可以同时是常量和易失性。我们可以一起使用常量和易失性变量。易失性和常量变量一起使用是在访问GPIO寄存器时。在这种情况下,如果开关或任何输出设备连接到GPIO,其值将由“外部因素”更改。在这种情况下,易失性变量很重要,因为它确保编译器始终从GPIO地址读取值,并避免做出任何假设。


22) 嵌入式C中的悬空指针是什么?

悬空指针是指向已被应用程序释放且不再使用的内存位置的指针。有时,程序员未能用有效地址初始化指针;这些类型的未初始化指针称为悬空指针。悬空指针发生在对象销毁时,此时对象被删除或从内存中释放,而未修改指针的值。如果您尝试解引用悬空指针,可能会导致运行时错误。


23) C中字符、整数、整数指针和字符指针的大小是多少?

在64位机器上,字符大小为1字节,整数大小为4字节,整数指针和字符指针大小为8字节;在32位机器上,分别为4字节。


24) 嵌入式处理器有哪些实时应用?

嵌入式处理器的一些实时应用包括

  • 洗碗机
  • 自动客车
  • 手机
  • 电视
  • 医疗设备等。

25) 航空航天应用中使用的嵌入式系统有哪些示例?

航空航天应用中使用的嵌入式系统的一些示例包括

  • 飞行控制系统
  • 自动驾驶模式
  • 乘客机上嵌入式系统
  • 发动机控制器
  • 起降控制器等。

26) 嵌入式软件支持多少位?

嵌入式软件支持8位、16位或32位嵌入式处理器。


27) 你如何理解NULL指针?它的用法是什么?

NULL是C中定义的宏。空指针是指不指向任何有效位置的指针。当我们要确保指针不指向任何有效位置并且不使用该指针进行任何更改时,会定义NULL指针。不使用空指针,我们就无法验证该指针是否指向任何有效位置。


28) 倒计时到零的循环比顺序计数循环更好吗?

是的,倒计时到零的循环比顺序计数循环更好,因为在循环终止时,编译器可以优化与零的比较。大多数处理器都有与零进行比较的指令。因此,它们不需要加载循环变量和最大值;将它们相减,然后与零进行比较。这就是为什么倒计时到零的循环更好的原因。


29) 汽车应用中的嵌入式系统有哪些示例?

以下是汽车应用中嵌入式系统的一些示例

  • 交通控制系统
  • 制动系统
  • 线控转向系统
  • 巡航控制应用
  • 安全气囊释放系统
  • 发动机管理单元等。

30) 使用嵌入式系统的家用电器有哪些示例?

以下是使用嵌入式系统的一些家用电器示例

  • 智能电视
  • 洗衣机
  • 微波炉
  • 洗碗机
  • 车库门控制器
  • 录像机和
  • 安防系统等。

31) 你如何理解嵌入式C中的结构体填充?

结构体填充是C编程语言中使用的一个概念。它用于在内存地址之间添加一个或多个空字节,以对齐内存中的数据。编译器会自动执行此操作,以确保所有成员都进行字节对齐。


32) 使用嵌入式系统概念的医疗设备有哪些示例?

以下是使用嵌入式系统概念的一些医疗设备示例

  • 麻醉监测系统
  • 心电图监视器
  • MRI扫描仪
  • 药物输送系统
  • 超声设备等。

33) 哪些国防系统使用嵌入式系统概念?

以下是使用嵌入式系统概念的一些国防系统示例

  • 无线电系统
  • 雷达系统
  • 导弹制导系统
  • 战斗机飞行控制系统
  • 目标制导系统等。

34) 你如何理解机器码?

机器码是计算机而不是程序员的语言。计算机只能接受机器码或目标代码形式的指令。当程序员解释代码时,它是复杂且容易出错的。无论是C、C++、Java等语言,所有软件最终都必须翻译成机器码才能由计算机执行。


35) 嵌入式系统中使用的分立元件有哪些?

嵌入式系统中使用的分立元件列表是

  • 晶体管
  • 二极管
  • 电阻器
  • 电容器

36) 振荡器频率与机器周期之间的联系是什么?

一个通用规则规定,振荡器频率直接决定应用程序的运行速度。因此,在大多数情况下,如果您将振荡器频率加倍,应用程序的速度也会加倍。


37) MIPS的全称是什么?

MIPS代表“百万指令每秒”(Million Instructions Per Second)。它是衡量计算机原始处理能力的一个近似度量。它可能会产生误导,因为测量技术经常不同,并且不同的计算机可能需要不同的指令集来执行相同的活动。


38) 如何提高8051微控制器的性能?

提高8051微控制器性能的最简单方法是提高时钟频率。8051微控制器允许使用远超原始设备12MHz限制的时钟速度。提高性能的最佳方法是对微控制器进行内部更改,以便执行每条机器指令所需的振荡器周期更少。


39) 8051微控制器最大振荡器频率范围和峰值性能是多少?

8051微控制器具有12 MHz的最大振荡器频率,峰值性能为1 MIP。


40) 你如何理解内存碎片?

内存碎片是在使用动态内存分配时出现的问题。随着时间的推移,当我们不断分配和释放内存空间时,最终我们将获得非连续的空闲内存块,并且我们正在使用的变量会散布在RAM的各个位置。这就是所谓的内存碎片。这可能会导致动态内存分配失败。例如,如果您需要分配一个包含100个整数的数组,而没有足够大的连续内存块,则会导致运行时错误。这就是为什么我们根本不在嵌入式系统固件中使用动态内存分配的原因。


41) 嵌入式C中的内联函数是什么?

内联函数是指其定义很小,可以在函数调用发生的地方进行替换的函数。ARM编译器支持使用`__inline`关键字的内联函数。这些函数具有小的定义,并且函数体在每次调用内联函数时都会被替换。


42) C语言中嵌入式系统的内存类型有哪些?

C语言中嵌入式系统的内存类型包括

  • DRAM(动态随机存取存储器)
  • SRAM(静态随机存取存储器)
  • 掩膜只读存储器(ROM)
  • PROM(可编程只读存储器)
  • UV EPROM(紫外线可擦除可编程只读存储器)
  • EEPROM(电可擦可编程只读存储器)