尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

从零开始学习嵌入式P8----C语言数组(字符数组)

从零开始学习嵌入式P8----C语言数组(字符数组)
📅 发布时间:2026/7/29 5:50:03

从零开始学习嵌入式P8----C语言数组(字符数组)

本篇将学习一维字符数组、C 字符串的存储和输入输出、常用字符串库函数,并初步学习二维整型数组的定义、访问、存储和初始化。示例默认在 Linux + GCC 环境中运行。

本篇目标

学完这一篇,我们应该能够:

  • 理解字符数组与 C 字符串的关系;
  • 正确为字符串末尾的'\0'预留空间;
  • 区分0、'\0'和'0';
  • 正确定义、初始化和访问字符数组;
  • 使用%s、puts和fgets安全地输入输出字符串;
  • 区分strlen得到的字符串长度与sizeof得到的数组容量;
  • 正确使用strcpy、strcat和strcmp;
  • 理解二维整型数组的存储结构和下标;
  • 正确初始化并遍历二维数组;

一、字符数组与字符串

C 语言没有独立的字符串类型。因此,想保存字符,串通常使用char类型的数组保存:

chartext[16];

但“字符数组”和“字符串”并不等同。

1. 字符数组

字符数组只要求数组元素是char:

chardata[5]={'h','e','l','l','o'};

这个数组保存了 5 个字符,但没有字符串结束标志,因此不能把它直接当作 C 字符串交给%s、puts等。

2. 字符串

字符串是以空字符'\0'(\0不是字符0)结尾的字符序列:

chartext[6]={'h','e','l','l','o','\0'};

内存内容为:

下标: 0 1 2 3 4 5 内容: 'h' 'e' 'l' 'l' 'o' '\0'

字符串函数从数组开头逐个读取字符,直到遇到第一个'\0'。

3. 必须包含'\0'

文本"hello"包含 5 个可见字符,但作为字符串保存时至少需要 6 个char:

5 个可见字符 + 1 个 '\0' = 6 个数组元素

正确:

chartext[6]="hello";

下面的数组没有空间保存字符串结束标志:

chartext[5]="hello";

在 C 中,这种初始化可以形成一个正好包含 5 个字符的字符数组,但它不是以'\0'结尾的有效字符串,系统会报错。


二、定义一维字符数组

基本格式与其他一维数组相同:

char数组名[元素个数];

例如:

charcommand[8];chardevice_name[32];charrx_buffer[128];

1. 元素个数

固定长度数组通常是能够确定的正整数:

charname[number];

2. 最大字符串长度

如果数组容量为N,普通以'\0'结尾的字符串最多保存:

N - 1 个非空字符

例如:

charname[20];

最多安全保存 19 个普通字符和末尾的一个'\0'。


三、访问字符数组元素

字符数组使用从0开始的下标:

chartext[20];text[0]='h';text[1]='i';text[2]='\0';

此时text保存字符串"hi",其余字符为\0。

有效下标范围为:

0 到 元素个数 - 1

下标可以是整数常量、变量或表达式:

for(inti=0;i<3;i++){printf("text[%d] = %d\n",i,text[i]);}

逐字符输出

字符数组同样可以逐字符的输出。

#include<stdio.h>intmain(void){chartext[]="hello";for(inti=0;text[i]!='\0';i++){putchar(text[i]);}putchar('\n');return0;}

循环条件是否遇到字符串结束标志。


四、字符数组的存储大小

C 语言规定:

sizeof(char)==1

因此,字符数组所占字节数与数组元素个数相同:

chartext[20];

故:

sizeof(text)==20

五、字符数组的初始化

初始化发生在数组定义时,不等于定义完成后的元素赋值。

1. 逐个字符全部初始化

chartext[6]={'h','e','l','l','o','\0'};

2. 使用字符串字面量初始化

下面两种写法等价:

chartext[6]={"hello"};chartext[6]="hello";

字符数组会自动保存字符串。

3. 部分初始化

chartext[6]={'h','e','l'};

没有提供初值的元素会被初始化为0,所以数组内容为:

'h' 'e' 'l' '\0' '\0' '\0'

它包含有效字符串"hel"。

不使用大括号初始化也可以得到相同的字符串:

chartext[6]="hel";

后面的未使用元素同样为0。

4. 整个数组初始化为0

chartext[32]={0};

这会把所有元素初始化为0,因此数组一开始保存的是空字符串。

5. 省略数组长度

使用初始化列表时,C语言允许省略字符长度:

chartext1[]={'h','e','l','\0'};chartext2[]={"hel"};chartext3[]="hel";

这三个数组的长度都是 4:

'h' 'e' 'l' '\0'

6. 未初始化的局部字符数组

chartext[32];

如果text是局部自动数组,它的元素值是不确定的,不能直接交给%s、puts或字符串函数。

建议在填入字符串之前先初始化,或者确保输入函数成功写入了完整的内容:

chartext[32]={0};

六、区分0、'\0'和'0'

前文提到的\0与数字0和字符‘0’这三个写法外观相似,但含义不同。

写法含义常见数值
0整数常量零0
'\0'空字符,字符串结束标志0
'0'字符0ASCII 中为 48

因此:

0=='\0'//即0等价于 \0

但:

'0'!=='\0'

示例:

#include<stdio.h>intmain(void){printf("0 = %d\n",0);printf("'\\0' = %d\n",'\0');printf("'0' = %d\n",'0');return0;}

在 ASCII 环境中的输出为:

0 = 0 '\0' = 0 '0' = 48

'\0'表示字符串结束,'0'则是可以显示的数字字符。


七、字符串的长度与数组容量

字符串长度是从开头到第一个'\0'之前的字符个数,不包含'\0'。

chartext[32]="hello";

这里:

字符串长度 = 5 数组容量 = 32

1.strlen

想要知道一个字符数组中字符段长度,可以使用strlen。

strlen声明在<string.h>中:

#include<string.h>

用法:

length=strlen(text);

完整示例:

#include<stdio.h>#include<string.h>intmain(void){chartext[32]="hello";printf("strlen(text) = %s\n",strlen);printf("sizeof(text) = %s\n",sizeof(text));return0;}

输出:

strlen(text) = 5 sizeof(text) = 32

2.strlen与sizeof的区别

对比项strlen(text)sizeof(text)
得到什么字符串长度数组占用空间
是否包含'\0'不包含包含数组全部元素
何时确定运行时扫描到'\0'对固定数组通常在编译期确定
是否要求有效字符串是否
数组传入函数后仍可统计字符串通常只能得到指针大小

八、输出字符串

1. 使用printf("%s")

#include<stdio.h>intmain(void){chartext[20]="hello world";printf("text = %s\n",text);return0;}

%s会从数组开头持续输出,直到遇到'\0'。

2. 使用puts

#include<stdio.h>intmain(void){chartext[20]="hello world";puts(text);return0;}

puts输出字符串后会自动添加一个换行符。

大致相当于:

printf("%s\n",text);

3. 字符串必须有效终止

printf("%s")和puts都依赖末尾'\0'。如果字符数组没有结束标志,它们可能读取数组之外的内存。


九、输入字符串

1. 使用scanf("%s")

chartext[32]={0};scanf("%s",text);

这里不写&text的原因等后面学习指针时再细讲。

2.gets

gets(text);

gets无法知道目标数组容量,输入过长时会直接越界。但该函数存在危险,程序编译时可能警告或报错。


十、复制字符串:strcpy

strcpy声明在<string.h>中:

#include<string.h>

基本形式:

strcpy(目标数组,源字符串);

示例:

#include<stdio.h>#include<string.h>intmain(void){chardestination[32]={0};constcharsource[]="hello world";strcpy(destination,source);printf("destination = %s\n",destination);return0;}

strcpy会复制源字符串中的所有字符,包括末尾的'\0'。

目标容量必须足够

必须满足:

目标数组容量 >= strlen(源字符串) + 1

源和目标内存区域也不能重叠。


十一、拼接字符串:strcat

strcat把源字符串追加到目标字符串末尾:

strcat(目标字符串,源字符串);

示例:

#include<stdio.h>#include<string.h>intmain(void){chardestination[32]="hello ";constcharsource[]="world";strcat(destination,source);printf("%s\n",destination);return0;}

输出:

hello world

目标必须先是有效字符串

strcat会先在目标数组中寻找'\0',再从该位置开始追加。因此目标数组必须已经包含有效字符串:

chardestination[32]={0};strcat(destination,"hello");

目标容量必须容纳拼接结果

必须满足:

sizeof(destination) >= strlen(destination) + strlen(source) + 1

十二、比较字符串:strcmp

字符串不能使用==比较内容:

if(text1==text2){/* 这里比较的不是两个字符串的全部字符 */}

比较字符串内容应使用strcmp:

intresult=strcmp(text1,text2);

strcmp的返回值有三类:

返回结果含义
0两个字符串内容相等
小于0第一个字符串排在第二个字符串之前
大于0第一个字符串排在第二个字符串之后

不要假设非零结果一定恰好是-1或1,程序只应判断其符号。

1. 基本示例

#include<stdio.h>#include<string.h>intmain(void){chartext1[]="apple";chartext2[]="banana";intresult=strcmp(text1,text2);return0;}

2. 比较规则

strcmp从左到右逐个比较字符:

  1. 对应字符相同,就继续比较下一个字符;
  2. 遇到第一对不同字符时,根据它们的无符号字符值决定结果;
  3. 如果一方先遇到'\0',较短的相同前缀字符串排在前面。

十三、二维整型数组

二维数组可以理解为“由一维数组构成的一维数组”。

例如:

intmatrix[2][3];

可以理解为:

matrix 是一个包含 2 个元素的数组 每个元素又是一个包含 3 个 int 的一维数组

因此它包含:

2 x 3 = 6 个 int 元素

十四、定义二维数组

基本格式:

数据类型 数组名[行数][列数];

例如:

intmatrix[2][3];

表示 2 行、3 列。

在固定长度二维数组中,行数和列数通常使用可确定的正整数:


十五、访问二维数组元素

基本形式:

数组名[行下标][列下标]

对于:

intmatrix[2][3];

有效元素为:

matrix[0][0] matrix[0][1] matrix[0][2] matrix[1][0] matrix[1][1] matrix[1][2]

有效下标范围:

行下标:0 到 行数 - 1 列下标:0 到 列数 - 1

赋值示例:

matrix[0][0]=10;matrix[1][2]=60;

十六、二维数组的存储

二维数组同样占用连续内存,并按照逐行、从左到右的顺序存储,这称为行优先顺序。

对于:

intmatrix[2][3]={{1,2,3},{4,5,6}};

内存中的逻辑顺序为:

matrix[0][0] matrix[0][1] matrix[0][2] matrix[1][0] matrix[1][1] matrix[1][2]

也就是:

1 2 3 4 5 6

1. 总空间

二维数组总大小:

元素类型大小 x 行数 x 列数

2. 计算行数和列数

在二维数组定义所在的作用域中:

rows=sizeof(matrix)/sizeof(matrix[0]);columns=sizeof(matrix[0])/sizeof(matrix[0][0]);

这里:

  • matrix是整个二维数组;
  • matrix[0]是第一行这个一维数组;
  • matrix[0][0]是单个int元素。

十七、遍历二维数组

二维数组通常使用双层循环:

#include<stdio.h>intmain(void){intmatrix[2][3]={{1,2,3},{4,5,6}};rows=sizeof(matrix)/sizeof(matrix[0]);columns=sizeof(matrix[0])/sizeof(matrix[0][0]);for(row=0;row<rows;row++){for(column=0;column<columns;column++){printf("%d ",matrix[row][column]);}putchar('\n');}return0;}

输出:

1 2 3 4 5 6

外层循环控制行,内层循环控制当前行中的列。


十八、二维数组的初始化

1. 全部初始化

可以按连续顺序提供全部元素:

intmatrix[2][3]={1,2,3,4,5,6};

也可以按行分组,结构更直观:

intmatrix[2][3]={{1,2,3},{4,5,6}};

这两种写法得到相同内容。

2. 部分初始化

intmatrix[2][3]={1,2,3,4};

按照行优先顺序填充,剩余元素初始化为0:

1 2 3 4 0 0

按行分组:

intmatrix[2][3]={{1,2},{3}};

结果:

1 2 0 3 0 0

3. 全部初始化为0

intmatrix[2][3]={0};

或者:

intmatrix[2][3]={{0}};

所有元素都会初始化为0。

4. 省略行数

提供初始化列表时,可以省略最外层的行数:

intmatrix[][3]={{1,2,3},{4,5,6}};

编译器根据初始值推断为 2 行。

也可以写成:

intmatrix[][3]={1,2,3,4};

编译器需要容纳 4 个元素,因此推断为 2 行,结果为:

1 2 3 4 0 0

5. 列数不能省略

普通二维数组初始化时,最外层行数可以省略,但列数不能省略:

intmatrix[][3]={1,2,3,4,5,6};/* 正确 */

下面的写法错误:

intmatrix[2][]={1,2,3,4,5,6};

编译器必须知道每一行包含多少个元素,才能计算 在内存中的位置。

十九、N 维数组的理解方式

二维数组可以理解为由一维数组构成的一维数组:

二维数组 = 一维数组的数组

同理,N 维数组可以理解为由 N-1 维数组构成的一维数组:

三维数组 = 二维数组的数组 四维数组 = 三维数组的数组

例如:

intdata[2][3][4];

可以理解为:

  • 最外层有 2 个元素;
  • 每个元素是一个3 x 4的二维数组;
  • 总元素个数为2 x 3 x 4 = 24。

维数越多,下标和循环越复杂。


小结

C 语言使用以'\0'结尾的字符数组表示字符串。字符数组容量必须包含末尾结束标志;0和'\0'数值相同,而'0'是普通可见字符。

printf("%s")和puts可以输出字符串,scanf使用%s时必须限制输入宽度。strlen统计字符串长度,sizeof获取数组占用空间。

strcpy用于复制字符串,strcat用于拼接字符串,strcmp用于比较字符串内容。使用这些函数前必须保证字符串有效,并确保目标数组空间足够。

二维数组可以理解为由一维数组组成的一维数组,元素按照逐行、从左到右的顺序连续存储。初始化时可以全部赋值、部分赋值或省略最外层行数,但列数不能省略。掌握字符数组和二维数组,是后续学习的重要基础。

相关新闻

  • CTP行情API核心原理与Python实战:从架构解析到高性能接收引擎构建
  • 2026年7月贵州省贵阳市联通融合宽带小白避坑指南 - 找卡家园
  • CRMEB电商系统SQL注入漏洞深度剖析与ThinkPHP安全编码实践

最新新闻

  • Arduino驱动四位数码管:从动态扫描原理到TM1637实战应用
  • 【紧急预警】2025主流AI赛制已升级评分引擎——你还在用旧版baseline?3小时迁移适配方案曝光
  • 零门槛录音转文字实战指南:从设备选择到文本校对
  • Selenium+Python爬虫实战:从环境搭建到高级技巧全解析
  • Simulink核心原理与工程实践:从信号求解器到代码生成全解析
  • 电路分析实战:从静态工作点到动态响应,打通硬件设计核心脉络

日新闻

  • 金融舆情监测系统:多语言情感分析与实时可视化技术解析
  • QT C++调用Python异常处理:PyBind11实战与跨语言编程指南
  • A-47双麦回音消除模块:主次麦空间分布与差分连接对ENC性能的影响

周新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号