Bootstrap

【C语言】C语言中的数组(详解)

目录

1.数组的定义

2.一维数组

2.1一维数组的创建和初始化

(1)一维数组的创建

(2)一维数组的初始化

a.不完全初始化:

b.完全初始化

2.2一维数组的引用

(1)数组的下标

(2)一维数组的打印

(3)一维数组的读入

(4)一维数组的类型

(5)利用sizeof 求数组大小

(6)一维数组在内存中的存放

3.二维数组的定义

3.1二维数组的创建和初始化

(1)二维数组的创建

(2)二维数组的初始化

a.不忘全初始化

b.完全初始化

3.2二维数组的引用

(1)二维数组的下标

(2)二维数组的打印

(3)二维数组的读入

(4)二维数组的类型

​编辑

(5)二维维数组在内存中的存放

4.变长数组


1.数组的定义

定义:数组是一个或多个相同类型元素的集合

从定义中可知,数组是可以一个也可以多个,其次,数组里面存储的元素数据类型相同

2.一维数组

2.1一维数组的创建和初始化

(1)一维数组的创建

一维数组按照以下格式创建
  type arr_name[常量值];
type 为数组的元素类型
arr_name 为我们创建的数组名
[ ]里面的常量值为我们指定数组的大小即元素个数
char op[10];//例如创建一个数组名名为 op 的数组,里面存放 10 个char 类型的数据

int arr[10];//例如创建一个数组名名为 arr 的数组,里面存放 10 个 int 类型的数据

double st[20];//例如创建一个数组名名为 st 的数组,里面存放 20 个 double 类型的数据

//……

根据数组的创建规则我们可以指定数组名,数组大小,元素类型但最好符合我们的实际需要

(2)一维数组的初始化

创建完数组后我们便可以对其进行初始化

数组的初始化可以是不完全初始化或者完全初始化

a.不完全初始化:

因为没有把数组中每个元素都进行初始化,所以就称为不完全初始化

//C语言中,如果数组元素没有进行初始化则默认系统默认为0

int arr[10] = {0};
//数组的元素个数为10,但初始化就初始化一个元素,所以第一个元素初始化为0,其他位置系统默认为0;

int arr[10] = {1,2,3,4};
//数组的元素个数为10,但初始化就初始化4个元素,所以第一,二,三,四个元素分别初始化为1,2,3,4,其他位置系统默认为0;

char str [6] = "hao";

char str [6] = {'h','a','o'};

b.完全初始化

将数组里面的元素都进行初始化即为完全初始化

完全初始化的方式
1.  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
//每个元素都被进行了初始化

2.  int arr[] = {1,2,3,4,5,6,7,8,9,10};
//这种方法比较特殊,我们在初始化的时候没有定义它的元素个数,所以系统就默认我们初始化的元素个数就为数组的大小,系统会自动帮我们计算数组的大小,并且按照顺序一一对数组中的元素进行赋值

字符类型数组确实出初始化:
1.char str [6] = "hello";
//数组的元素个数为6,但初始化就初始化5个元素,所以第一,二,三,四,五个元素分别初始化为'h','e','l',''l,'o',然后最后一个位置刚好用来放 ' \0 '

2.char str [6] = {'h','e','l','l','o','\0'};
//数组的元素个数为6,但初始化就初始化5个元素,所以第一,二,三,四,五个元素分别初始化为'h','e','l',''l,'o',然后最后一个位置用来放 ' \0 '

错误用法:
char str [5] = "hello";
char str [5] = {'h','e','l','l','o'};
都没留位置给 '\0';

这里需要注意的是数组初始化的时候,必须满足我们要初始化的元素个数 <= 数组大小,否则系统会报错,特别是字符类型数组初始化的时候还应该留一个位置给字符串结束符号  ' \0 ' ,否则用的时候会出错

%s 是用来打印字符串的内容,那为什么会打印出hello后打印出一串不认识的字符呢?

因为 %s 从开始读读到字符串结束符号 ' \0 ' 就会自动停止读下去,我们在进行初始化结束的时候

系统会自动在字符串末尾加上 ' \0 ',前提是要有位置可以存放 ' \0 ',但是我们刚好把数组上的位置

都填满了,就放不下 '  \0 ',所以打印的时候就会一直打印,直到遇到有 '  \0 ' 的位置才停止打印

打开监视可以看到str[5]的位置确实为'  \0 ',也证实了系统会自动为我们存放 '  \0 '

2.2一维数组的引用

(1)数组的下标

数组[ ]里面的常量值就是我们所说的数组下标,它比较特殊,例如我们创建了含n个元素的数组,它的第1个元素的下标是从0开始,而不是从1开始,所以最后一个元素的下标就为n-1

现在我们知道数组的下标了,如果我们想要利用数组中的某个元素时,我们还要知道下标引用操作符 [ ] ,通过这个操作符和下标我们就可以找到并访问数组中的每一个元素,进行相关操作

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

//例如我们要对数组中第四个元素进行赋值为5

arr[3] = 5;

(2)一维数组的打印

如果我们要把数组中的每一个元素打印再屏幕上,我们可以利用 for 循环 访问到每一个元素

运行结果

(3)一维数组的读入

和上面的打印原理一样,都是利用 for 循环

运行结果

(4)一维数组的类型

数组的类型就是去掉数组名剩下的部分

例如我们创建了一个数组  int arr[10]; 该数组的类型就为 int [10];

我们知道sizeof 是一个专门计算数据类型和表达式大小的操作符,单位为字节

因为该数组由10个int 类型的数据组成,所以所占的空间大小为40个字节,刚好等于屏幕上打印的

数值,更加说明了数组是有类型的并且数组的类型为去掉数组名剩下的部分

(5)利用sizeof 求数组大小

但我们在创建数组时没有指定数组大小直接初始化,当我们需要知道数组的大小时,也可以利用

sizeof 来求得数组的大小(特别说明一下:数组名单独出现的时候大部分情况下代表数组的地址,

但除了sizeof(arr)和& arr 除外,这两个代表的是整个数组)

(6)一维数组在内存中的存放

这个%p 是专门用来打印地址的占位符,其打印在屏幕是以十六进制打印的,从运行结果就可知相邻两项之间总是相差4的字节,因为数组中的每个元素类型都是 int 类型占4个字节,所以就可以得出一维数组在内存中是连续存放的

数组元素首地址
arr[0]008FF7D4
arr[1]008FF7D8
arr[2]008FF7DC
arr[3]008FF7E0
arr[4]008FF7E4
arr[5]008FF7E8
arr[6]008FF7EC
arr[7]008FF7F0
arr[8]008FF7F4
arr[9]008FF7F8

3.二维数组的定义

当某个数组的元素是由类型相同一维数组组成的,则我们称此数组为二维数组

3.1二维数组的创建和初始化

(1)二维数组的创建

二维数组按照以下格式创建

type arr_name[常量值][常量值];

type 为二维数组的元素类型

arr_name 为二维数组的数组名

第一个[ ]里的常量值为二维数组的行数(也可以看成有几个一维数组)

第二个[ ]里的常量值为二维数组的列数(也可以看成一维数组数组大小)

int arr[10][10];

//创建一个数组名名为 arr 的二维数组,其行数为10,列数也为10,每个元素的类型都为 int 类型

char str[5][5];

//创建一个数组名名为 str 的二维数组,其行数为5,列数也为5,每个元素的类型都为 char 类型

//......

(2)二维数组的初始化

二维数组的初始化也就可以分为不完全初始化和完全初始化

a.不忘全初始化
//这里我们定义一个3行5列的二维数组,对他进行不同方式的不完全初始化

1.int arr[3][5] = {0,1,2};
//初始化四个元素,即arr[0][1] = 0,arr[0][1] = 1,arr[0][2] = 2,其他位置默认为0


2.int arr[3][5] = {0,1,2,3,4,5,6};
//初始化7个元素,即arr[0][0] = 0,arr[0][1] = 1,arr[0][2] = 2 , arr[0][3] = 3,arr[0][4] = 4,arr[1][0] = 5,arr[1][1] = 6,其他位置默认为0
//所以从中可以看出来二维数组初始化一行上的每个元素后,紧接着初始化下一行


3.int arr[3][5] = {{0,1,2},{5,6}};
//这种方法我们换一个角度理解,把二维数组看成是一个一维数组,它的每个元素为一维数组
//第外层的花括号可以看成是一维数组初始化时候的那个大括号,里面的每一个成对的花括号可以看成是
//一个元素,只不过每个元素是一个一维数组
//所以arr[0][0] = 0,arr[0][1] = 1,arr[0][2] = 2 ,arr[1][0] = 5,arr[1][1] = 6,其他位置默认为0


4.int arr[][5] = {0,1,2,3,4,5,6};
//初始化数组的时候可以把行省略,但是列不可以省略,行的话系统会自己帮我们数
//即arr[0][0] = 0,arr[0][1] = 1,arr[0][2] = 2 , arr[0][3] = 3,arr[0][4] = 4,arr[1][0] = 5,arr[1][1] = 6,其他位置默认为0


5.int arr[][5] = {{0,1,2,3},{5,6}};
//这种方法同第3种方法一样,就是不同的是它省略了行,但是系统会自己数
//即arr[0][0] = 0,arr[0][1] = 1,arr[0][2] = 2 , arr[0][3] = 3,arr[1][0] = 5,arr[1][1] = 6,其他位置默认为0
b.完全初始化
int arr[2][5] = {0,1,2,3,4,6,7,8,9};

int arr[2][5] = {{0,1,2,3,4},{5,6,7,8,9}};

int arr[][5] = {0,1,2,3,4,6,7,8,9};

int arr[][5] = {{0,1,2,3,4},{5,6,7,8,9}};
//以上的几种方法初始化结果都是
//arr[0][0] = 0,arr[0][1] = 1,arr[0][2] = 2,arr[0][3] = 3,arr[0][4] = 4
//arr[1][0] = 5,arr[1][1] = 6,arr[1][2] = 7,arr[1][3] = 8,arr[1][4] = 9,

3.2二维数组的引用

(1)二维数组的下标

二维数组的行下标和列下标也都是从0开始,如果行或列都有n个元素,则最后一个元素下标为n-1

下图最上边的为列号,最左侧的为行号,有了行号和列号就可以迅速找出二维数组中的某个元素,例如例如我们要找5,则可以通过行号1列号4迅速找到5

(2)二维数组的打印

如果要把二维数组中的每一个元素打印在屏幕上可以利用两层for循环访问每一个元素从而进行打印

(3)二维数组的读入

如果要一些数据依次读入赋值二维数组中的部分或全部元素,则我们也可以利用两层 for 循环进行读入

(4)二维数组的类型

跟上面一维数组一样,二维数组的类型也是除去数组名剩下的部分

(5)二维维数组在内存中的存放

利用循环打印出二维数组的地址

因为我们存储的数据为整型变量,一个整型占4个字节,所以打印出来可以发现每相邻两项之间都是相差4个字节,说明二维数组在内存中也是连续存放的

数组元素元素地址元素内容
arr[0][0]00C4F82C0
arr[0][1]00C4F8301
arr[0][2]00C4F8342
arr[0][3]00C4F8383
arr[0][4]00C4F83C4
arr[1][0]00C4F8401
arr[1][1]00C4F8442
arr[1][2]00C4F8483
arr[1][3]00C4F84C4
arr[1][4]00C4F8505

4.变长数组

所谓的变长数组就是数组的大小可以由变量来确定,但只要创建完一个数组后,这个数组的大小就不会再改变,这时候就不能在通过修改变量来修改数组的空间大小了

在C99标准之前,数组的大小都应该是常量值或者常量表达式,亦或者创建数组的时候忽略数组大小,不能为变量,这样就有一个缺点:就是会对内存空间造成浪费,但在C99标准新增了一个规定,就是数组的大小可以是一个变量现在的VS不支持变长数组,否则会报错,但是再Dev-C++或小熊猫上面是支持的

变长数组的优点:可以根据需要比较精确的确定数组大小,减少对空间的浪费,比较灵活

变长数组的缺点:就是创建数组的时候不能进行初始化

好了,今天的数组就介绍到这里,希望对您由帮助!

;