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. 踩坑提醒
  1. 不能使用char**接收二维字符数组,类型不匹配,运行直接崩溃;
  2. 传参必须写明列长度,否则编译器无法计算行偏移,编译报错。

二、指针数组传参(二级指针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(开发最常用)

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

  1. 定义与初始化
// 定义学生结构体类型
struct Student {
    char name[20];
    int age;
    float score;
};
// 指定成员初始化(推荐)
struct Student s = {.name = "WangWu", .age = 19, .score = 94};
  1. 成员访问规则
  • 普通结构体变量:. 访问 s.age = 20;
  • 结构体指针变量:-> 访问 struct Student *p = &s; p->score = 96;
  1. 内存对齐规则(笔试必考)
  • 成员地址必须是自身类型字节整数倍;
  • 结构体总大小 = 最大基础类型字节的整数倍;
  • #pragma pack(1) 关闭对齐,按1字节紧凑存储。
  1. 函数传参规范
    优先使用结构体指针地址传递,减少大内存拷贝开销,同时支持修改外部原始数据。
  2. 易错点
    结构体指针误用.;递归结构体不能定义自身变量,只能定义自身指针;忽略内存对齐导致空间计算错误。
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;

四、今日全部易错点总结

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

五、学习总结

  1. 多行字符串分两种存储:二维字符数组(可修改、固定宽度)、字符指针数组(静态常量、省内存),对应两套不同传参方案,不能混用;
  2. 指针是数组传参核心难点,分清数组指针、指针数组、一级/二级指针的区别是关键;
  3. 构造类型中结构体是业务开发核心,共用体、枚举作为辅助工具;结构体指针传参、内存对齐是笔试面试高频考点;
  4. 所有字符串操作必须重视\0结束符,数组访问严格控制边界,避免内存越界问题。
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐