嵌入式学习9

C语言学习笔记:二维字符数组 + 函数全解(避坑总结)

一、今日学习内容总览

今天重点学习两大模块:二维字符型数组(字符串数组存储多行文本)、C语言函数完整体系(定义/调用/声明、变量作用域、存储类型、值传递),配套Linux gcc编译运行环境,整理开发规范与高频踩坑点。

二、二维字符型数组

1. 核心作用

一维字符数组仅存储单个字符串;二维字符数组可存放多个字符串,用于多行文本、单词列表、菜单等场景。

2. 定义格式

char 数组名[行数][列数];
  • 行数:最多存储字符串数量;
  • 列数:单个字符串最大长度,必须预留\0结束符空间

示例:

// 最多5个字符串,单串最大31字符+1位\0
char str[5][32];

3. 元素访问规则

  1. str[i][j]:访问第i个字符串第j个单个字符,类型char
  2. 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. 核心重点

  1. 每行是独立一维字符数组,每行末尾自动补\0
  2. 列数必须常量,行数可省略,编译器自动根据字符串数量推导;
  3. 内存逐行连续存储,包含所有字符与结束符;
  4. 字符串库函数直接接收str[i]作为参数。

6. 注意点 & 易踩坑

  1. 列数不足,无\0%s打印乱码、内存越界;
  2. 禁止整体赋值:str[0] = "test"; 编译报错,改用strcpy(str[0], "test");
  3. scanf("%s", str[i]) 遇空格截断,带空格文本用fgets
  4. 下标越界读写数组,篡改其他变量内存;
  5. 局部数组未初始化,元素为随机垃圾值,建议定义时={0}清空。

三、C语言函数完整知识点

1. 函数核心价值

  1. 消除重复代码,代码复用;
  2. 模块化拆分逻辑,降低维护难度;
  3. 单一函数只实现单一功能,解耦业务逻辑。

2. 函数三要素:定义、调用、声明

(1)函数定义(完整实现)

语法:

返回值类型 函数名(形参类型1 形参1, 形参类型2 形参2,...)
{
    函数逻辑;
    return 返回值;
}

规则:

  1. 函数名命名规则同变量;
  2. 无返回值必须写void,省略返回值默认int
  3. return返回值与函数类型不一致时,自动强制转换;
  4. void函数可写return; 提前终止,无需返回数据。

示例:闰年判断函数

int isLeapYear(int year)
{
    if((year%4==0 && year%100!=0) || (year%400==0))
        return 1;
    return 0;
}
(2)函数调用

语法:函数名(实参1, 实参2);

  1. 实参可为常量、变量、表达式;
  2. 实参与形参个数、顺序一一对应,类型不匹配自动隐式转换;
  3. 函数调用是表达式,拥有返回值,可赋值、打印、逻辑判断。

调用示例:

int flag = isLeapYear(2000);
printf("是否闰年:%d\n", flag);
(3)函数声明

作用:告知编译器函数签名,解决「函数定义在调用下方」编译报错。
格式(去掉函数体,保留头部):

int isLeapYear(int year);

使用规则:

  • 函数写在main上方:无需声明;
  • 函数写在main下方:文件头部提前声明;
  • 多文件开发:声明统一放入.h头文件。

3. 变量作用域 & 生命周期

(1)作用域(可访问范围)
  1. 局部变量:定义在{}内部,仅当前大括号可用;
  2. 全局变量:所有函数外部定义,整个.c文件任意位置访问。
(2)生命周期(内存存在时长)
  1. auto局部变量:进入作用域分配栈空间,出{}立刻回收;
  2. static静态变量、全局变量:程序编译分配静态区,程序结束才释放。

4. 四大存储类型

语法:存储类型 数据类型 变量名;

关键字存储区域初始化特性特性说明
auto(默认)栈区未初始化=随机值局部变量默认类型,出括号销毁
registerCPU寄存器随机值加速访问,无空闲寄存器则退化为auto
extern静态区仅声明,不可赋值调用其他文件全局变量/函数
static数据段静态区未初始化自动置01.局部static:仅本函数可见,只初始化一次
2.全局static:仅当前文件可见,避免多文件重名
程序内存分区
  1. 文本区:存放程序代码、指令;
  2. 数据区:全局/static变量、字符串常量;
  3. 堆区:程序员手动malloc/free管理;
  4. 栈区:auto局部变量、函数调用栈帧;
  5. 寄存器:register变量临时存储。

5. 值传递(C语言默认传参方式)

  1. 实参仅拷贝数值给形参,形参是独立内存副本;
  2. 函数内修改形参,完全不影响外部原始实参;
  3. 如需修改外部变量,后续学习指针传递实现。

6. 函数核心重点

  1. 必须先声明/定义,后调用;
  2. 有返回值函数每条逻辑分支建议配置return
  3. static局部变量仅初始化一次,多次调用保留上次结果;
  4. static修饰全局变量/函数,限制作用域为本文件,解决多文件命名冲突。

7. 函数高频踩坑点

  1. 自定义函数写在main下方,缺少函数声明,编译警告/报错;
  2. 混淆值传递特性,试图修改外部实参无效果;
  3. auto局部变量未初始化直接参与运算,结果随机错乱;
  4. static局部变量误以为每次调用都会重新初始化;
  5. 函数部分分支缺少return,返回随机垃圾值;
  6. 无限制滥用全局变量,代码耦合度高,BUG难以定位;
  7. 函数形参漏写数据类型,语法报错。

四、整体开发避坑汇总

二维字符数组坑

  1. 列数未预留\0,字符串打印乱码、内存越界;
  2. 直接对字符串数组行整体赋值,编译报错;
  3. 数组下标越界读写,破坏其他变量内存;
  4. scanf("%s")读取带空格字符串,自动截断内容。

函数开发坑

  1. 缺少函数声明;
  2. 值传递无法修改外部变量;
  3. 局部变量未初始化直接运算;
  4. static变量初始化逻辑理解错误;
  5. 函数分支缺少return;
  6. 全局变量滥用耦合代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值