云计算百科
云计算领域专业知识百科平台

嵌入式学习14

C语言进阶:二维字符数组传参、指针数组传参、结构体/共用体/枚举(构造类型)详解

前言

今天系统学习了多行字符串两种存储结构的函数传参:二维字符数组、字符指针数组,同时完整梳理C语言三大构造数据类型结构体、共用体、枚举。这部分是C语言中指针与复合类型结合的高频难点,面试、笔试常考,本文整理核心知识点、使用规范、高频易错点,方便复习收藏。

一、二维字符数组传参(多行连续字符串)

1. 适用场景

需要固定每行字符串最大长度,允许修改每行字符,内存连续存储,例如存储学生姓名、固定长度文本。
定义示例:

// 5行字符串,每行最多32字节(包含\\0结束符)
char str[5][32] = {"apple", "banana", "orange", "pear", "grape"};

2. 函数传参标准写法

二维数组传参列数不可省略,底层为数组指针 char (*p)[列数]:

// 数组指针标准形式
void PrintStrArr(char (*pstr)[32], int row_cnt);
// 等价语法糖写法
void PrintStrArr(char pstr[][32], int row_cnt);

调用直接传入数组名:

PrintStrArr(str, 5);

3. 底层原理

数组名str代表一整行的地址,str+1会一次性偏移32字节,跳转到下一行字符串;函数内访问元素pstr[i][j]和外部完全通用。

4. 踩坑提醒
  • 不能使用char**接收二维字符数组,类型不匹配,运行直接崩溃;
  • 传参必须写明列长度,否则编译器无法计算行偏移,编译报错。
  • 二、指针数组传参(二级指针char**,字符串常量数组)

    1. 适用场景

    存储静态字符串常量,每行长度不统一,节省内存,多用于菜单、英文单词表、固定提示文本。
    定义示例:

    // 数组存储5个字符串指针,字符串存只读常量区
    char *p_str[5] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};

    2. 函数传参标准写法

    指针数组本质是一级指针数组,传参使用二级指针char**接收:

    void PrintPointArr(char **ppstr, int len);

    调用方式:

    PrintPointArr(p_str, 5);

    3. 两种字符串数组核心区分
    存储方式传参类型字符可修改内存特点
    char arr[N][M] char (*)[M] 支持修改每行字符 连续二维内存,固定行宽
    char *arr[N] char** 常量字符串不可修改 仅存储指针,字符串独立存放
    4. 高频易错

    指针数组指向"xxx"常量字符串时,禁止修改字符:p_str[0][0]='X'会访问只读内存,触发段错误。

    三、C语言构造数据类型 struct / union / enum

    3.1 结构体 struct(开发最常用)

    结构体封装不同类型成员,用来描述一组关联属性,学生信息、日期、坐标都依赖结构体实现。

  • 定义与初始化
  • // 定义学生结构体类型
    struct Student {
    char name[20];
    int age;
    float score;
    };
    // 指定成员初始化(推荐)
    struct Student s = {.name = "WangWu", .age = 19, .score = 94};

  • 成员访问规则
    • 普通结构体变量:. 访问 s.age = 20;
    • 结构体指针变量:-> 访问 struct Student *p = &s; p->score = 96;
  • 内存对齐规则(笔试必考)
    • 成员地址必须是自身类型字节整数倍;
    • 结构体总大小 = 最大基础类型字节的整数倍;
    • #pragma pack(1) 关闭对齐,按1字节紧凑存储。
  • 函数传参规范
    优先使用结构体指针地址传递,减少大内存拷贝开销,同时支持修改外部原始数据。
  • 易错点
    结构体指针误用.;递归结构体不能定义自身变量,只能定义自身指针;忽略内存对齐导致空间计算错误。
  • 3.2 共用体 union

    所有成员共享同一块内存,空间大小等于最大成员占用字节,同一时间仅一个成员有效,多用于硬件数据解析、类型转换。

    union Temp {
    int num;
    char buf[4];
    };

    赋值num后,buf数组数据会被覆盖,反之同理。

    3.3 枚举 enum

    批量定义int类型常量,限制变量合法取值,可读性优于#define宏,自带类型校验。

    enum Color {RED, GREEN, BLUE=10};
    enum Color c = RED;

    四、今日全部易错点总结

  • 传参混淆二维字符数组(数组指针)与指针数组(二级指针),类型不匹配程序崩溃;
  • 结构体指针使用.访问成员,语法报错;
  • 字符串未预留\\0结束符,数组越界输出乱码;
  • 修改指针数组指向的常量字符串,触发段错误;
  • 计算结构体大小时忽略内存对齐规则;
  • 共用体同时读写多个成员,数据相互覆盖错乱;
  • 二维数组传参省略列长度,编译直接报错。
  • 五、学习总结

  • 多行字符串分两种存储:二维字符数组(可修改、固定宽度)、字符指针数组(静态常量、省内存),对应两套不同传参方案,不能混用;
  • 指针是数组传参核心难点,分清数组指针、指针数组、一级/二级指针的区别是关键;
  • 构造类型中结构体是业务开发核心,共用体、枚举作为辅助工具;结构体指针传参、内存对齐是笔试面试高频考点;
  • 所有字符串操作必须重视\\0结束符,数组访问严格控制边界,避免内存越界问题。
  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » 嵌入式学习14
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!