嵌入式面试八股文(二十)·C语言关键字相关知识点速通(static、const、volatile、struct、enum、union)

目录

[1. 解释 C 语言中的 static 关键字的作用](#1. 解释 C 语言中的 static 关键字的作用)

[2. const 关键字在 C 语言中如何使用](#2. const 关键字在 C 语言中如何使用)

[3. 解释 volatile 关键字的重要性](#3. 解释 volatile 关键字的重要性)

[4. 什么是指针?并举例说明其用法](#4. 什么是指针?并举例说明其用法)

[5. 解释结构体(struct)在 C 语言中的使用](#5. 解释结构体(struct)在 C 语言中的使用)

[6. 枚举(enum)类型在 C 语言中的作用](#6. 枚举(enum)类型在 C 语言中的作用)

[7. 解释 C 语言中的联合(union)](#7. 解释 C 语言中的联合(union))


1. 解释 C 语言中的 static 关键字的作用

static 关键字在C语言中核心作用有3类,在嵌入式开发中应用广泛,核心是控制生命周期和作用域:

  • 修饰局部变量:变量存储在静态存储区,生命周期与程序一致,仅初始化1次,函数调用结束后值不丢失。嵌入式场景中常用于统计中断触发次数、保存设备运行状态等,例如:
cpp 复制代码
void exti_isr(void) 
{
    static uint32_t interrupt_count = 0; // 仅初始化1次,持续保存计数
    interrupt_count++; // 每次中断触发,计数递增
}
  • 修饰全局变量:限制该变量的作用域仅为当前编译单元(.c文件),避免多文件命名冲突,是嵌入式模块化开发的基础,防止全局变量被其他文件误修改。
  • 修饰函数:限制函数的作用域仅为当前编译单元,仅能在本文件中被调用,避免函数名冲突,同时隐藏内部实现细节,提升代码安全性和可维护性。

2. const 关键字在 C 语言中如何使用

const 用于定义"只读"元素,核心作用是保护数据不被误修改,在嵌入式开发中常用于硬件寄存器、配置参数等场景,具体用法分为4类:

  • 修饰普通变量:定义只读变量,初始化后不可修改,例如 const int MAX_BUFFER_SIZE = 128;,常用于定义设备配置参数(如缓冲区大小、波特率)。
  • 修饰指针(核心用法,嵌入式高频):
cpp 复制代码
#define GPIOA_BASE 0x40010800
const uint32_t *const GPIOA_CRL = (uint32_t *)(GPIOA_BASE + 0x00); // 只读寄存器,不可修改指针和内容

const int *p:指针指向的内容只读,指针本身可修改(常用于读取硬件寄存器值,防止误写);

int *const p:指针本身只读,指向的内容可修改(常用于固定指向某一硬件寄存器地址);

const int *const p:指针和指向的内容均只读(最严格的保护,常用于核心寄存器)。

  • 修饰数组:定义只读数组,例如 const char device_name[] = "STM32F103";,常用于存储设备固定信息(设备名、版本号)。
  • 修饰函数参数:防止函数内部修改传入的参数值,例如 void print_info(const char *info),避免误修改传入的字符串或数据。

3. 解释 volatile 关键字的重要性

volatile 核心作用:告诉编译器该变量可能被硬件、中断、其他线程异步修改,禁止编译器对该变量的读写进行优化,确保每次读写都直接访问内存(而非寄存器缓存),是嵌入式开发中避免"优化陷阱"的关键,直接影响系统稳定性。

重要性体现在2个核心场景:

  • 硬件相关变量:嵌入式中,硬件寄存器的值可能被外设异步修改(如GPIO输入电平、ADC采样值),若不加volatile,编译器会优化为缓存到寄存器,导致读取到旧值,例如:
cpp 复制代码
// 错误:未加volatile,编译器可能优化为只读取一次
uint32_t *gpio_input = (uint32_t *)0x40010804;
while(*gpio_input == 0); // 若硬件修改了gpio_input的值,可能无法检测到

// 正确:加volatile,每次读取都访问内存
volatile uint32_t *gpio_input = (volatile uint32_t *)0x40010804;
while(*gpio_input == 0); // 能实时检测硬件电平变化
  • 中断相关变量:中断服务程序中修改的全局变量,主程序读取时若不加volatile,编译器会优化为缓存值,导致主程序无法获取中断修改后的值(如中断标志位、计数变量)。

4. 什么是指针?并举例说明其用法

指针:本质是存储内存地址的变量,通过指针可以直接访问内存中的数据,是C语言的核心特性,也是嵌入式开发中操作硬件、优化内存的关键。

核心用法及嵌入式实例:

  • 访问硬件寄存器(嵌入式最核心用法):通过指针直接操作寄存器地址,实现对硬件的控制,例如操作STM32的GPIO输出高电平:
cpp 复制代码
#define GPIOA_ODR 0x4001080C // GPIOA输出数据寄存器地址
volatile uint32_t *gpioa_odr = (volatile uint32_t *)GPIOA_ODR;
*gpioa_odr |= (1 << 0); // 通过指针修改寄存器,PA0输出高电平
  • 操作数组:指针可替代数组下标,访问效率更高,例如:
cpp 复制代码
int data[] = {1,2,3,4,5};
int *p = data; // 指针p指向数组首地址
for(int i=0; i<5; i++)
{
    printf("%d ", *(p+i)); // 通过指针访问数组元素,等价于data[i]
}
  • 动态内存分配:通过指针接收malloc分配的内存地址,实现灵活的内存管理,例如:
cpp 复制代码
int *buf = (int *)malloc(10 * sizeof(int)); // 分配10个int类型的内存
if(buf != NULL)
{
    buf[0] = 100; // 通过指针操作动态内存
    free(buf); // 释放内存,避免泄漏
    buf = NULL; // 避免野指针
}
  • 函数参数传递:通过指针传递参数,实现"传址调用",让函数修改外部变量的值,例如:
cpp 复制代码
void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
int x=1, y=2;
swap(&x, &y); // 传递变量地址,函数内部修改x和y的值

5. 解释结构体(struct)在 C 语言中的使用

结构体(struct)是C语言中用于自定义复合数据类型的工具,可将多个不同类型的数据(如int、char、指针)封装在一起,形成一个统一的"数据集合",适合描述具有多个属性的对象,在嵌入式开发中应用极广(如设备参数、传感器数据、通信帧)。

核心用法及嵌入式实例:

  • 定义结构体类型:
cpp 复制代码
// 定义传感器数据结构体,包含温度、湿度、时间戳
typedef struct {
    float temperature; // 温度(单位:℃)
    float humidity;    // 湿度(单位:%RH)
    uint32_t timestamp;// 时间戳(单位:ms)
} SensorData;

// 定义GPIO配置结构体
typedef struct {
    uint8_t pin;       // GPIO引脚号
    uint8_t mode;      // 工作模式(输入/输出)
    uint8_t speed;     // 输出速度
} GPIO_Config;
  • 声明结构体变量并使用:
cpp 复制代码
// 声明结构体变量
SensorData sensor;
// 赋值
sensor.temperature = 25.5;
sensor.humidity = 60.0;
sensor.timestamp = 1680000000;
// 访问结构体成员
printf("温度:%.1f℃\n", sensor.temperature);

// 结构体指针(嵌入式高频用法,节省内存)
SensorData *p_sensor = &sensor;
printf("湿度:%.1f%%RH\n", p_sensor->humidity); // 指针访问用->
结构体数组:存储多个同类型的复合数据,例如存储多个传感器的采集数据:SensorData sensor_array[5]; // 5个传感器的数据
for(int i=0; i<5; i++){
    sensor_array[i].temperature = 25.0 + i;
    sensor_array[i].humidity = 60.0 - i;
}

6. 枚举(enum)类型在 C 语言中的作用

枚举(enum)是C语言中用于定义一组有名字的常量(枚举常量)的工具,核心作用是替代魔法数字,让代码更具可读性、可维护性,避免因数字含义不明确导致的错误,在嵌入式开发中常用于表示状态、模式、命令等。

核心用法及嵌入式实例:

  • 定义枚举类型:
cpp 复制代码
// 定义设备运行状态枚举
typedef enum {
    DEVICE_IDLE = 0,    // 空闲状态
    DEVICE_COLLECTING,  // 采集状态
    DEVICE_COMMUNICATING,// 通信状态
    DEVICE_ERROR        // 错误状态
} DeviceStatus;

// 定义GPIO模式枚举
typedef enum {
    GPIO_INPUT = 0,     // 输入模式
    GPIO_OUTPUT,        // 输出模式(默认递增1,即1)
    GPIO_AF,            // 复用功能模式(2)
    GPIO_ANALOG         // 模拟模式(3)
} GPIOMode;
  • 使用枚举变量:
cpp 复制代码
DeviceStatus status = DEVICE_IDLE; // 声明枚举变量并赋值
// 分支判断(可读性远高于if(status == 0))
switch(status){
    case DEVICE_IDLE:
        printf("设备处于空闲状态\n");
        break;
    case DEVICE_COLLECTING:
        printf("设备正在采集数据\n");
        break;
    case DEVICE_ERROR:
        printf("设备出现错误\n");
        break;
}
  • 作用总结:枚举常量是编译期常量,不占用运行时内存;可清晰表示一组相关的状态/选项,降低代码维护成本(如修改状态值,只需修改枚举定义,无需修改所有使用处)。

7. 解释 C 语言中的联合(union)

联合(union)又称共用体,是C语言中一种复合数据类型,核心特点是:所有成员共用同一块内存空间,内存大小等于最大成员的大小,同一时间只能有一个成员有效。

核心作用及嵌入式实例:

  • 节省内存:当多个数据不同时使用时,用union可减少内存占用,嵌入式系统内存资源有限,此特性尤为重要。
  • 数据类型转换:通过union实现同一内存空间的不同数据类型解读(如将4字节int拆分为4个1字节char,或反之),常用于通信数据解析(如串口接收的字节流转换为多字节数据):
cpp 复制代码
// 定义联合,用于int和char的转换
typedef union {
    int32_t data;       // 4字节
    uint8_t byte[4];    // 4个1字节,与data共用内存
} DataConvert;

// 实例:将int数据拆分为字节流,用于串口发送
DataConvert dc;
dc.data = 0x12345678; // 赋值int类型
// 拆分后,byte[0]=0x78, byte[1]=0x56, byte[2]=0x34, byte[3]=0x12(小端模式)
for(int i=0; i<4; i++){
    uart_send_byte(dc.byte[i]); // 逐字节发送
}
  • 注意:union的成员共用内存,修改一个成员会覆盖其他成员的值,使用时需确保同一时间只操作一个成员。

千题千解·嵌入式工程师八股文详解_时光の尘的博客-CSDN博客

相关推荐
会编程的土豆2 小时前
c语言时间戳从入门到精通
linux·c语言·算法
悠哉悠哉愿意2 小时前
【单片机学习笔记】math库函数补充
c语言·笔记·单片机·学习
炸膛坦客2 小时前
单片机/C语言八股:(五)32/64 位系统中,C/C++各变量类型所占字节数
c语言·开发语言·c++
会编程的土豆2 小时前
C语言实现:影院票务管理系统(铠甲怪兽管理系统)(详细解析+效果展示)C语言实现:影院票务管理系统(铠甲怪兽管理系统)(详细解析+效果展示)
c语言·开发语言·课程设计·项目·管理系统
2301_789015622 小时前
DS进阶:红黑树
c语言·开发语言·数据结构·c++·算法·r-tree·lsm-tree
daxi1502 小时前
C语言从入门到进阶——第13讲:深入理解指针(3)
c语言·开发语言·数据结构·算法
老鱼说AI2 小时前
祖师爷KR的C语言讲解:第6期-输入与输出
c语言·开发语言
夜天炫安全6 小时前
数据结构中所需的C语言基础
c语言·数据结构·算法
BUG_MeDe11 小时前
json格式字符串解析的简单使用 libjson-c
c语言·开发语言·json