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**,字符串常量数组)
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;
网硕互联帮助中心





评论前必须登录!
注册