嵌入式学习 day8:字符数组与二维数组
2026/7/29 5:23:34 网站建设 项目流程

一、字符数组概述

C语言没有专门的字符串类型,一切字符串操作都靠字符数组完成

c

char str[20]; // 定义一个能存20个字符的数组

1. 字符数组的存储

字符数组的每个元素存一个字符,末尾用'\0'(ASCII码为0)标识字符串结束。

c

char str[6] = {'h', 'e', 'l', 'l', 'o', '\0'}; // 内存布局:h e l l o \0

💡感悟'\0'是字符串的"终止符",它告诉printfputs"到这里就停了"。没有它,函数会一直往下读内存里的垃圾数据,直到碰巧遇到一个0为止——这就是为什么字符数组初始化时一定要考虑'\0'的位置。

2. 三个容易混淆的"零"

写法含义ASCII码
0整数零00000000
'\0'字符串结束符00000000(与0等价)
'0'字符零00110000(48)

💡感悟0'\0''0'这三个东西看起来像,实际完全不同。刚开始写代码的时候经常搞混,尤其是用strlen统计长度时,明明字符串里有'0'字符,长度却按实际字符数算——因为strlen只认'\0'作为结束标志,而'0'只是普通字符。搞清楚它们之间的区别,字符串相关的代码就少了一半的Bug。


二、字符数组的初始化

1. 全部初始化

c

char str[6] = {'h', 'e', 'l', 'l', 'o', '\0'}; char str[6] = {"hello"}; // 自动加 \0 char str[6] = "hello"; // 最常用写法

2. 部分初始化

c

char str[6] = {'h', 'e', 'l', 'l', 'o'}; // 少了 \0,剩余元素补0(即 \0) // str 内容是:h e l l o \0 char str[6] = {'h', 'e'}; // 剩余4个元素自动补0 char str[6] = {0}; // 全部置零,常用写法

💡感悟:部分初始化自动补0的特性,在清空字符串时特别实用——写一个char str[32] = {0};,整个数组就全是'\0'了,不用写循环逐个赋值。这是C语言提供的"语法糖",用好了能省不少事。

3. 默认初始化(省略数组长度)

c

char str[] = {'h', 'e', 'l', 'l', 'o', '\0'}; char str[] = {"hello"}; char str[] = "hello"; // 长度为6(包含\0)

⚠️ 实际开发中不建议省略长度,容易造成数组越界。


三、字符串的输入与输出

1. 输出方式

c

char str[20] = "hello world"; printf("str = %s\n", str); // %s 控制符专门输出字符串 puts(str); // 输出后自动加换行

⚠️putsprintf多打印一个换行符。

2. 输入方式

c

char str[32] = {0}; scanf("%s", str); // 不能接收带空格的字符串 gets(str); // 可以接收带空格的字符串(但不安全,已废弃)

scanf 与 gets 的区别

scanf("%s")gets()
能否接收空格❌ 遇到空格停止✅ 整行读取
安全性较好不检查边界,已废弃

💡感悟gets已经被废弃了,因为它不检查数组边界,输入过长会导致缓冲区溢出。实际项目中推荐用fgets替代。虽然学校练习里可能还会用gets,但心里要清楚——写代码不光要能用,还要安全


四、字符串常用操作

1. 获取字符串长度 —— strlen

c

char str[32] = "hello"; int len = strlen(str); // len = 5(不含 \0)

⚠️strlen统计的是从开头到'\0'之间的字符个数,不包含'\0'sizeof获得的是数组占用总字节数。

c

char str[32] = "hello"; printf("%lu\n", strlen(str)); // 5 printf("%lu\n", sizeof(str)); // 32

2. 字符串拷贝 —— strcpy

c

char str[32] = {0}; strcpy(str, "hello world"); // 将 "hello world" 拷贝到 str 中

⚠️ 目标空间必须足够大,否则会内存越界访问。

3. 字符串拼接 —— strcat

c

char str1[32] = "hello"; char str2[32] = "world"; strcat(str1, str2); // str1 变为 "helloworld"

⚠️ 目标空间必须能容纳拼接后的完整字符串。

💡感悟strcat的工作原理是先找到目标字符串的'\0',然后从这里开始往后面粘贴源字符串的内容,最后再补一个'\0'。理解了这个过程,就明白了为什么目标数组要足够大——否则'\0'被覆盖后找不到结束位置,程序就会越界访问。

4. 字符串比较 —— strcmp

c

int ret = strcmp(str1, str2); // ret == 0 → 两个字符串相等 // ret > 0 → str1 大于 str2 // ret < 0 → str1 小于 str2

比较规则:从左到右逐字符比较ASCII码,第一个不同的字符决定大小。

💡感悟:字符串比较不是比长短,而是比"字典序"——"apple"和"banana"比较,先看第一个字符 'a' vs 'b','a' 小,所以整体就小,后面的字符都不用看了。这和查字典是一个道理。


五、二维数组

1. 定义与访问

二维数组本质上是"数组的数组"——可以理解为一个表格。

c

int a[2][3]; // 2行3列 // 元素:a[0][0] a[0][1] a[0][2] // a[1][0] a[1][1] a[1][2]

2. 存储顺序

二维数组在内存中按行连续存储,先存第0行,再存第1行。

c

int a[2][3] = {1, 2, 3, 4, 5, 6}; // 内存布局:1 2 3 4 5 6

3. 初始化

c

// 全部初始化 int a[2][3] = {1, 2, 3, 4, 5, 6}; int a[2][3] = {{1, 2, 3}, {4, 5, 6}}; // 按行清晰 // 部分初始化(未赋值的补0) int a[2][3] = {1, 2, 3, 4}; int a[2][3] = {{1, 2}, {3}}; // 默认初始化(行可省,列不可省) int a[][3] = {1, 2, 3, 4, 5, 6}; // 自动推断为2行

⚠️ 二维数组行数可以省略(编译器自动推断),但列数不能省略

4. 二维字符数组

存储多个字符串时用二维字符数组:

c

char str[3][10] = {"hello", "world", "C"}; // 存放3个字符串,每个最长9个字符(留1个给\0)

六、今日总结

今天学习了字符数组二维数组,核心要点如下:

字符数组(字符串)

  1. '\0'标识字符串结束,0'\0''0'要区分清楚

  2. 初始化推荐char str[32] = {0};char str[32] = "hello";

  3. 输入用scanf("%s")(无空格)或gets(可空格,但不安全)

  4. 常用函数:strlen(求长度)、strcpy(拷贝)、strcat(拼接)、strcmp(比较)

  5. 操作字符串时务必保证数组空间足够,防止越界

二维数组

  1. 本质是"数组的数组",按行连续存储

  2. 定义:数据类型 数组名[行数][列数]

  3. 初始化时行可省,列不可省

今日总结感悟

字符数组让我第一次意识到——原来C语言里压根没有"字符串类型"这种东西,所谓的字符串就是普通字符数组加上一个'\0''的约定。这就是C语言的设计哲学:不提供复杂的封装,只提供简单的原材料,怎么用全看你。习惯了高级语言字符串的同学可能觉得不方便,但正是这种"不替你做决定"的设计,给了程序员最大的掌控力。

字符串函数的练习我建议自己动手实现一遍——用循环写一个strlen、写一个strcpy,能帮你真正理解字符串在内存中是怎么存放和操作的。在纸上画一画数组的格子,填上字符,比盯着代码硬想要有效得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询