C语言数组介绍
2026/7/23 18:24:31 网站建设 项目流程

文章目录

  • 一、数组的概念
  • 二、一维数组
    • 1. 一维数组的创建
    • 2. 一维数组的初始化
    • 3. 数组的类型
    • 4. 一维数组的使用
    • 5. 一维数组在内存中的存储
    • 6. sizeof计算数组元素个数
  • 三、二维数组
    • 1. 二维数组的概念
    • 2. 二维数组的创建
    • 3. 二维数组的初始化
    • 4. 二维数组的使用
    • 5. 二维数组的输入和输出
    • 6. 二维数组在内存中的存储
    • 7. 二维数组中对于数组名的理解
  • 四、字符数组
    • 1. 字符串常量
    • 2. 指针存储字符串常量
    • 3. 数组存储字符串常量

一、数组的概念

数组一组相同类型元素的集合;从这个概念中我们就可以发现2个有价值的信息:

数组中存放的是1个或者多个数据,但是数组元素个数不能为0。
数组中存放的多个数据,类型是相同的。

数组分为一维数组和多维数组,多维数组中一般比较常见的是二维数组。

二、一维数组

1. 一维数组的创建

一维数组创建的语法如下:
存放在数组中的值被称为数组的元素,数组在创建的时候可以指定数组的大小和数组的元素类型。
type指定的是数组中存放数据的类型,可以是: char、short、int、float等,也可以是自定义的类型。
arr_name指的是数组的名字,这个名字根据实际情况,起的有意义就行。(注意不要跟关键字重名)
[ ]中的常量值是用来指定数组的大小的(元素个数),数组的大小根据实际的需求指定就行。
需要注意在创建数组时,[ ]中要给的是一个常量才可以,不能给变量。[ ]中可以直接使用常量,常量表达式或者宏定义都可以。示例:

#include<stdio.h>#defineNUM6intmain(){intarr1[10];intarr2[2+3];charch[NUM];return0;}

2. 一维数组的初始化

在创建数组的同时,给一些初始值,这种就称为数组的初始化。那数组如何初始化呢? 数组的初始化一般使用大括号,将数据放在大括号中:

//完全初始化intarr1[5]={1,2,3,4,5};//不完全初始化intarr2[5]={1};//第一个元素初始化为1,剩下的元素默认初始化为0

3. 数组的类型

数组也是有类型的,数组算是一种自定义类型,去掉数组名留下的就是数组的类型。例如:

intarr[10];charch[5];

arr数组的类型为int [10],ch数组的类型为char [5]。

4. 一维数组的使用

学习了一维数组的基本语法,一维数组可以存放数据,存放数据的目的是对数据进行操作,那我们如何使用一维数组呢?
(1) 数组下标
C语言规定数组是有下标的,下标从0开始,假设数组有n个元素,最后一个元素的下标是n-1,下标就相当于数组元素的编号,如下:

intarr[10]={1,2,3,4,5,6,7,8,9,10};

在C语言中,对于数组的访问提供了一个操作符[ ],这个操作符叫:下标引用操作符
有了下标引用操作符,我们就可以轻松的访问数组的元素了,比如我们访问下标为6的元素,我们就可以使用arr[6],想要访问下标是4的元素,就可以使用arr[4],如下代码:

#include<stdio.h>intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};printf("%d\n",arr[6]);printf("%d\n",arr[4]);return0;}

运行结果:
(2) 数组元素的打印
如果想在屏幕上打印数组的元素,就用for循环产生0~9的下标,使用下标访问数组的元素即可:

#include<stdio.h>intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};inti=0;for(i=0;i<10;i++){printf("%d ",arr[i]);}return0;}

运行结果:
(3) 数组元素的输入
可以根据自己的需要,用scanf函数给数组输入值,存入到数组中。给数组输入想要的数据:

#include<stdio.h>intmain(){intarr[10]={0};inti=0;for(i=0;i<10;i++){scanf("%d",&arr[i]);}for(i=0;i<10;i++){printf("%d ",arr[i]);}return0;}

运行结果:

5. 一维数组在内存中的存储

一维数组在内存中是怎样存储的呢?我们通过下面一段代码来看:

#include<stdio.h>intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};inti=0;for(i=0;i<10;i++){printf("&arr[%d]=%p\n",i,&arr[i]);}return0;}

运行结果:
从输出的结果可以发现,数组随着下标的增长,地址是由小到大变化的,并且我们发现每相邻两个元素之间相差4(因为一个整型是4个字节)。所以我们得出结论:数组在内存中是连续存储的

6. sizeof计算数组元素个数

在遍历数组的时候,我们经常想知道数组的元素个数,那C语言中有办法使用程序计算数组的元素个数吗? 答案是有的。通过sizeof可以求数组的元素个数。sizeof是一个操作符,用来计算类型或者变量的大小(单位字节)。sizeof也可以用来计算数组的大小:

#include<stdio.h>intmain(){intarr[10]={0};printf("%d\n",sizeof(arr));return0;}

运行结果:
输出的结果为40,计算的是整个数组所占内存空间的大小,单位是字节(数组名单独放在sizeof中,计算的是整个数组的大小)。又因为数组中所有元素的类型是相同的,所以只要计算出一个元素的大小,那数组的元素个数就可以计算出来了。我们通常选择计算第一个元素的大小:

#include<stdio.h>intmain(){intarr[10]={0};//计算数组中第一个元素的大小printf("%d\n",sizeof(arr[0]));//计算数组的元素个数intsz=sizeof(arr)/sizeof(arr[0]);printf("%d\n",sz);return0;}

运行结果:
可以看到,第一个元素的大小为4(字节),计算出的数组元素个数为10。以后在代码中需要数组元素个数的地方就不用固定写死了,这种计算数组元素个数的方式,不管数组怎么变化,计算出的大小也会随之变化。

三、二维数组

1. 二维数组的概念

上面学习的数组叫一维数组,数组的元素都是内置类型的。如果把一维数组做为数组的元素,这时候就是二维数组。二维数组作为数组元素的数组被称为三维数组,二维数组以上的数组统称为多维数组

2. 二维数组的创建

如何创建二维数组呢?语法形式是什么?如下:
例如:

intarr[3][5];doubledata[2][7];

上面的第一行代码,就是一个整型的二维数组。其中:
3表示有3行;5表示有5列,总共有3*5=15个元素。
int表示数组的每个元素是整型类型。
arr是数组名,可以根据自己的需要指定名字(注意不能和关键字重名)。
第二行代码是一个双精度浮点型二维数组。

3. 二维数组的初始化

在创建数组的同时,给一些初始值,就叫数组的初始化。二维数组的初始化也跟一维数组类似,使用大括号初始化:
(1) 不完全初始化

intarr1[3][5]={1,2};intarr2[3][5]={0};

在屏幕上打印这两个数组:
可以看到上面对于两个二维数组不完全初始化的打印结果,对于arr1数组,只初始化了两个元素,即从第一行的一维数组的第一个元素开始,从左往右依次初始化。如果一行的元素值给够了,就会从下一行一维数组的第一个元素开始从左往右初始化。对于没有给到值的元素会默认初始化为0。arr2数组只初始化了第一行的第一个元素为0,其余元素默认初始化为0。如下:
(2) 完全初始化

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

在屏幕上打印arr3数组的内容:
完全初始化就很好理解了:在创建二维数组的同时,对二维数组的所有元素都给一个初始值,就叫作完全初始化,对于{ }里的值,会从左往右,依次给到二维数组对应的元素。如果一行的值够了,就会从数组下一行的一维数组的第一个元素开始从左往右初始化。
(3) 按照行进行初始化
什么叫按照行进行初始化?其实就是按照二维数组的每个一维数组进行初始化,在二维数组的大括号{ }内部,会明确的给出每个一维数组,对每个一维数组进行初始化。例如:

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

打印出数组的内容,如下图样式:
可以看到上面的二维数组按照行进行初始化,在大括号的内部明确给出了二维数组的每个一维数组,因为一维数组的内容也是用大括号括起来的。所以在二维数组里对每一行进行初始化是遵循一维数组的初始化原则的。
(4) 二维数组初始化时可以省略行,但不能省略列
二维数组在创建并初始化时,可以省略行数,但是不能省略列数:

intarr5[][5]={1,2,3};intarr6[][5]={1,2,3,4,5,6,7};intarr7[][5]={{1,2},{3,4},{5,6}};

上面三个数组得到数组形式会是:
可以看到当数组给出列数却没有给出行数时,系统会根据你大括号里初始化数据的多少,自行计算数组的行数,确定数组是什么类型。

4. 二维数组的使用

二维数组的访问也是使用下标的形式进行的,二维数组是有行和列的,只要锁定了行和列就能唯一锁定数组中的一个元素。C语言规定:二维数组的行是从0开始的,列也是从0开始的,如下所示:

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

上图中,最左侧的灰色数字表示行号,最上面一行的橙色数字表示列号,可以发现下标都是从0开始。比如:行号为2,列号为3的元素,就是6:

#include<stdio.h>intmain(){intarr[3][5]={1,2,3,4,5,2,3,4,5,6,3,4,5,6,7};printf("%d\n",arr[2][3]);return0;}

运行结果:

5. 二维数组的输入和输出

上面讲过一维数组的访问,是通过下标进行的,用for循环产生对应的下标。二维数组也是一样的,也是通过下标来访问,只不过二维数组有行和列两个下标,如果要对二维数组进行输入输出的话,就要使用两个for循环,外层循环控制每一行的循环,内层的循环控制每一行里所有元素个数(列数)的循环。比如我们要输入和打印上面的arr数组在屏幕上,行的范围是0~2,列的范围是0~4,用两个for循环产生相应的行和列号:

#include<stdio.h>intmain(){intarr[3][5]={1,2,3,4,5,2,3,4,5,6,3,4,5,6,7};inti=0;//输入for(i=0;i<3;i++)//产生行号{intj=0;for(j=0;j<5;j++)//产生列号{scanf("%d",&arr[i][j]);//输入数据}}//输出for(i=0;i<3;i++)//产生行号{intj=0;for(j=0;j<5;j++)//产生列号{printf("%d ",arr[i][j]);//打印数据}printf("\n");}return0;}

输入数据后得到的结果:

6. 二维数组在内存中的存储

与一维数组一样,如果想知道二维数组在内存中的存储方式,我们也是可以打印出数组所有元素的地址的。代码如下:

#include<stdio.h>intmain(){intarr[3][5]={0};inti=0;intj=0;for(i=0;i<3;i++){for(j=0;j<5;j++){printf("&arr[%d][%d]=%p\n",i,j,&arr[i][j]);}}return0;}

运行结果:
从输出的结果来看,每一行内部的元素两两都是相邻的,地址之间相差4个字节,跨行位置处的两个元素(如: arr[0][4]和arr[1][0])之间也是差4个字节,所以得到的结论是:二维数组在内存中也是连续存储的

7. 二维数组中对于数组名的理解

在二维数组中,数组名表示什么含义?我们之前讲过一维数组的数组名是表示数组首元素的地址,也就是数组中第一个元素的地址。那二维数组的数组名其实也表示数组首元素的地址,但是这个首元素是指哪个呢?这里我们要把二维数组看成一维数组。举个例子:

intarr[3][4]={0};

二维数组其实可以看作是由一维数组构成的数组,也就是把每行的一维数组整体看做是一个元素,则二维数组现在就相当于一个一维数组,数组的首元素就是第一行的一维数组,则数组名就是第一行一维数组的地址,它是一个数组指针。就像上面的arr[3][4]数组,数组名arr表示的是第一行一维数组的地址,它是一个int(*)[4]类型的数组指针:即arr==&arr[0]

二维数组去掉列下标部分就是一维数组的数组名,如下:
数组名表示的是数组首元素的地址。则二维数组去掉列下标后的数组名,如上面的arr[0]、arr[1]和arr[2]分别表示二维数组中每行一维数组的首元素地址,即每个一维数组的第一个元素的地址,类型是int*的指针:arr[0]==&arr[0][0]arr[1]==&arr[1][0]arr[2]==&arr[2][0]
所以在二维数组中要区分开上面的两种数组名,不能混淆,尤其是在sizeof操作符中放有关数组名的各种表达式时,要特别区分上面的两种数组名。

四、字符数组

1. 字符串常量

字符串常量(也叫字符串字面量)是用双引号括起来的字符序列,例如:

"hello world""abc"""// 空字符串

字符串常量本质上是一个字符数组,编译器会自动在末尾添加’\0’作为结束标志。例如 “hello” 实际占用了6个字节:‘h’,‘e’,‘1’,1’,‘o’,‘\0’。

🍓字符串常量通常存储在程序的只读数据段(.rodata)中,程序运行期间不可修改。

2. 指针存储字符串常量

char*pstr="hello world";

上面这种将字符串常量的地址(即第一个字符的地址)存放在一个指针变量中,这样的话就不能通过pstr去修改这个字符串常量:

pstr[0]='H';// 程序会报错:未定义行为(UB)!试图修改只读内存

因为指针指向的是只读区,通过它修改内容会导致:

● 段错误(Segmentation Fault)
● 或其他未定义行为

正确的写法应该是:

constchar*pstr="hello world";//推荐加const修饰,防止误修改

3. 数组存储字符串常量

如果是用数组的形式去存储字符串常量,那就可以正常的修改字符串常量中的字符:

chararr[]="hello world";// 编译器将字符串复制到栈上存储arr[0]='H';

这种在函数内部创建的局部数组其实是在栈区存放着,所以可以修改数组元素。
char arr[] = "hello"的本质是:

chararr[]={'h','e','l','l','o',' ','w','o','r','l','d','\0'};

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

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

立即咨询