嵌入式软件开发中常见知识点问答集锦!

1 const关键字的具体作用和用途?

const主要用来修饰只读变量,告诉编译器:这个标识符所指向的内容是只读的,如果程序试图修改它,编译器就会直接报错。其作用体现在安全性、可读性两个方面。

常见用途:

(1)用来修饰只读变量,比如定义一个常数 const double PI =3.1415926;

或者定义一个常数数组 const graph\[\]={0x01, 0x02, 0x03, 0x04}; 可以拦截修改操作,减少BUG;

(2)修饰函数参数,比如修饰一个函数的形参,该形参在函数内部不能被修改,避免误操作,同时提高代码的可读性(一眼就看出这个参数是"输入型"参数,只读取不修改)。

cpp 复制代码
// const修饰char* str:限定函数内部不能修改str指向的字符串内容
void print_str(const char* str)
{
    // str[0] = 'H';  // 编译报错:assignment of read-only location '*str'
    printf("字符串:%s\n", str);
}

2 volatile关键字的具体作用和用途?

volatile的主要作用是告诉编译器:这个变量可能被外部触发条件(比如硬件、中断、线程等改变)意外修改,编译器不用对变量进行任何修改,每次读取变量时都是从内存中读取,而不是从寄存器中读取缓存值。

常见用途:

(1)访问硬件寄存器

硬件寄存器的值会被硬件自动修改,程序必须实时读取内存中的真是值。为达到访问硬件寄存器真实值的目的,比如用一个指针指向某个寄存器地址,然后加上volatile。

cpp 复制代码
// 示例:读取硬件串口数据寄存器(伪代码,模拟嵌入式场景)
#include <stdio.h>

// 定义串口数据寄存器的内存地址(volatile修饰,强制每次读内存)
#define UART_DATA_REG (*(volatile unsigned char*)0x1000)

// 读取串口数据,直到有数据可读
unsigned char read_uart_data() {
    // 编译器不会优化这个循环:每次都从0x1000内存地址读真实值
    while (UART_DATA_REG == 0) {
        // 等待硬件传入数据
    }
    return UART_DATA_REG;  // 读取最新的硬件数据
}

int main() {
    unsigned char data = read_uart_data();
    printf("串口读取到的数据:%d\n", data);
    return 0;
}

(2)中断/多线程中的共享变量

在中断服务程序或者多线程程序中,一个变量可能被中断或者其它线程修改,volatile能保证每次访问的都是内存中的最新值。

cpp 复制代码
// 示例:中断程序中的共享标志位(伪代码)
#include <stdio.h>

// 共享标志位:被主程序和中断程序共同访问,必须加volatile
volatile int interrupt_flag = 0;

// 模拟中断处理函数(硬件触发时执行)
void interrupt_handler() {
    interrupt_flag = 1;  // 中断触发,修改标志位
}

int main() {
    // 主循环:检测中断标志位
    while (1) {
        // 不加volatile的话,编译器可能优化成:只读一次interrupt_flag,之后永远用这个值
        // 加了volatile后,每次都读内存中的最新值
        if (interrupt_flag == 1) {
            printf("检测到中断,处理中...\n");
            interrupt_flag = 0;  // 清除标志位
            break;
        }
    }
    return 0;
}

3 static关键字的具体作用和用途?

static修饰的变量,存储在全局区/静态区,在程序运行期间一直存在可以随时读写;同时限制全局变量和函数的作用域在当前.c文件。主要起到一个隐藏、封装变量/函数,避免暴露不必要的接口。

常见用途

(1)修饰全局变量

限制作用域:限制全局变量的作用域在当前.c文件,其它外部.c文件不能对该变量进行读写,起到一个隐藏和封装细节的作用。

避免命名冲突:允许多个.c文件命名相同名字的变量,避免"重命名"报错。

(2)修饰函数

限制作用域:限制全局变量的作用域在当前.c文件,其它外部.c文件不能对该变量进行读写,起到一个隐藏和封装细节的作用。

避免命名冲突:允许多个.c文件命名相同名字的变量,避免"重命名"报错。

(3)修饰数组

static修饰数组时,本质和修饰变量一致,核心是将数组存储到静态区,避免栈溢出(栈空间通常较小,大数组建议用static)。

cpp 复制代码
#include <stdio.h>

void big_array() {
    // 普通大数组:栈空间不足,可能导致栈溢出
    // int arr[1024*1024];  // 4MB数组,栈通常只有几MB,易崩溃
    // static数组:存储在静态区,无栈溢出风险
    static int arr[1024*1024] = {0};
    arr[0] = 10;
    printf("static数组第一个元素:%d\n", arr[0]);
}

int main() {
    big_array();
    return 0;
}

可见,static在多人协助的场合应用居多,每人专注自己的程序模块。

相关推荐
炸膛坦客11 小时前
单片机/C/C++八股:(二十六)IIC 专题(I²C)---- 上集
c语言·c++·单片机
程序员Rock19 小时前
上位机开发-MODBUS面试常见问题
c语言·c++·面试·职场和发展·上位机
GeekArch19 小时前
第24讲:Vibe模式代码风格控制——适配Keil/STM32工程规范
人工智能·stm32·单片机·嵌入式硬件·mcu·决策树·ai编程
Freedom_my20 小时前
STM32项目3
stm32·单片机·嵌入式硬件
国科安芯21 小时前
星间光链路:AS32S601型抗辐射MCU在空间激光通信终端控制中的技术实现
服务器·网络·单片机·嵌入式硬件·物联网·安全·信息与通信
小李不困还能学1 天前
基于 51 单片机的8 路抢答器设计教程
单片机·嵌入式硬件·mongodb·抢答器
萌动的小火苗1 天前
嵌入式开发中的栈与队列:任务调度为什么依赖数据结构
数据结构·c++·单片机·嵌入式硬件
振浩微433射频芯片1 天前
工业遥控器总在关键时刻“掉链子”?——433MHz芯片方案如何破局
网络·单片机·嵌入式硬件·物联网·工业遥控
blevoice1 天前
抖抖燃脂机单 AC6966B 主控调试踩坑:Type-C 整机供电喇叭无声排障
c语言·开发语言·单片机
小小晓.1 天前
C++小白记:C风格字符串和数组用法
c语言·开发语言·c++