C语言学习笔记:二维字符数组 + 函数全解(避坑总结)
一、今日学习内容总览
今天重点学习两大模块:二维字符型数组(字符串数组存储多行文本)、C语言函数完整体系(定义/调用/声明、变量作用域、存储类型、值传递),配套Linux gcc编译运行环境,整理开发规范与高频踩坑点。
二、二维字符型数组
1. 核心作用
一维字符数组仅存储单个字符串;二维字符数组可存放多个字符串,用于多行文本、单词列表、菜单等场景。
2. 定义格式
char 数组名[行数][列数];
- 行数:最多存储字符串数量;
- 列数:单个字符串最大长度,必须预留
\0结束符空间。
示例:
// 最多5个字符串,单串最大31字符+1位\0
char str[5][32];
3. 元素访问规则
str[i][j]:访问第i个字符串第j个单个字符,类型char;str[i]:代表第i个完整字符串,可直接传入printf、字符串操作函数。
4. 五种标准初始化写法
// 1. 逐字符初始化
char str[5][32] = {
{'h','e','l','l','o','\0'},
{'w','o','r','l','d','\0'}
};
// 2. 内层大括号规范写法
char str[5][32] = {{"hello"}, {"world"}};
// 3. 最简省略内层括号(推荐)
char str[5][32] = {"hello", "world", "how", "are", "you"};
// 4. 全部初始化为空串
char str[5][32] = {0};
// 5. 省略行数,列数不可省略
char str[][32] = {"hello", "world"};
5. 核心重点
- 每行是独立一维字符数组,每行末尾自动补
\0; - 列数必须常量,行数可省略,编译器自动根据字符串数量推导;
- 内存逐行连续存储,包含所有字符与结束符;
- 字符串库函数直接接收
str[i]作为参数。
6. 注意点 & 易踩坑
- 列数不足,无
\0:%s打印乱码、内存越界; - 禁止整体赋值:
str[0] = "test";编译报错,改用strcpy(str[0], "test");; scanf("%s", str[i])遇空格截断,带空格文本用fgets;- 下标越界读写数组,篡改其他变量内存;
- 局部数组未初始化,元素为随机垃圾值,建议定义时
={0}清空。
三、C语言函数完整知识点
1. 函数核心价值
- 消除重复代码,代码复用;
- 模块化拆分逻辑,降低维护难度;
- 单一函数只实现单一功能,解耦业务逻辑。
2. 函数三要素:定义、调用、声明
(1)函数定义(完整实现)
语法:
返回值类型 函数名(形参类型1 形参1, 形参类型2 形参2,...)
{
函数逻辑;
return 返回值;
}
规则:
- 函数名命名规则同变量;
- 无返回值必须写
void,省略返回值默认int; return返回值与函数类型不一致时,自动强制转换;void函数可写return;提前终止,无需返回数据。
示例:闰年判断函数
int isLeapYear(int year)
{
if((year%4==0 && year%100!=0) || (year%400==0))
return 1;
return 0;
}
(2)函数调用
语法:函数名(实参1, 实参2);
- 实参可为常量、变量、表达式;
- 实参与形参个数、顺序一一对应,类型不匹配自动隐式转换;
- 函数调用是表达式,拥有返回值,可赋值、打印、逻辑判断。
调用示例:
int flag = isLeapYear(2000);
printf("是否闰年:%d\n", flag);
(3)函数声明
作用:告知编译器函数签名,解决「函数定义在调用下方」编译报错。
格式(去掉函数体,保留头部):
int isLeapYear(int year);
使用规则:
- 函数写在
main上方:无需声明; - 函数写在
main下方:文件头部提前声明; - 多文件开发:声明统一放入
.h头文件。
3. 变量作用域 & 生命周期
(1)作用域(可访问范围)
- 局部变量:定义在
{}内部,仅当前大括号可用; - 全局变量:所有函数外部定义,整个
.c文件任意位置访问。
(2)生命周期(内存存在时长)
- auto局部变量:进入作用域分配栈空间,出
{}立刻回收; - static静态变量、全局变量:程序编译分配静态区,程序结束才释放。
4. 四大存储类型
语法:存储类型 数据类型 变量名;
| 关键字 | 存储区域 | 初始化特性 | 特性说明 |
|---|---|---|---|
| auto(默认) | 栈区 | 未初始化=随机值 | 局部变量默认类型,出括号销毁 |
| register | CPU寄存器 | 随机值 | 加速访问,无空闲寄存器则退化为auto |
| extern | 静态区 | 仅声明,不可赋值 | 调用其他文件全局变量/函数 |
| static | 数据段静态区 | 未初始化自动置0 | 1.局部static:仅本函数可见,只初始化一次 2.全局static:仅当前文件可见,避免多文件重名 |
程序内存分区
- 文本区:存放程序代码、指令;
- 数据区:全局/static变量、字符串常量;
- 堆区:程序员手动malloc/free管理;
- 栈区:auto局部变量、函数调用栈帧;
- 寄存器:register变量临时存储。
5. 值传递(C语言默认传参方式)
- 实参仅拷贝数值给形参,形参是独立内存副本;
- 函数内修改形参,完全不影响外部原始实参;
- 如需修改外部变量,后续学习指针传递实现。
6. 函数核心重点
- 必须先声明/定义,后调用;
- 有返回值函数每条逻辑分支建议配置
return; - static局部变量仅初始化一次,多次调用保留上次结果;
- static修饰全局变量/函数,限制作用域为本文件,解决多文件命名冲突。
7. 函数高频踩坑点
- 自定义函数写在main下方,缺少函数声明,编译警告/报错;
- 混淆值传递特性,试图修改外部实参无效果;
- auto局部变量未初始化直接参与运算,结果随机错乱;
- static局部变量误以为每次调用都会重新初始化;
- 函数部分分支缺少
return,返回随机垃圾值; - 无限制滥用全局变量,代码耦合度高,BUG难以定位;
- 函数形参漏写数据类型,语法报错。
四、整体开发避坑汇总
二维字符数组坑
- 列数未预留
\0,字符串打印乱码、内存越界; - 直接对字符串数组行整体赋值,编译报错;
- 数组下标越界读写,破坏其他变量内存;
scanf("%s")读取带空格字符串,自动截断内容。
函数开发坑
- 缺少函数声明;
- 值传递无法修改外部变量;
- 局部变量未初始化直接运算;
- static变量初始化逻辑理解错误;
- 函数分支缺少return;
- 全局变量滥用耦合代码。

224

被折叠的 条评论
为什么被折叠?



