第 5 章 数组

        数组是一种存储相同类型的元素的集合。数组可以是一维的,也可以是多维的。字符串是由字符组成的字符数组。


5.1 数组的定义和使用

        在C语言中,数组是一种用来存储同一类型的多个元素的数据结构。数组可以存储整数、字符、浮点数等类型的数据。它可以存储一个固定大小的相同类型元素的顺序集合。

        数组的声明并不是单独声明一个个的变量,而是声明一个数组变量,然后通过使用 runoob[0]、runoob[1]、...、runoob[99] 来代表一个个单独的变量。

        所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。数组说明见下图5-1。

图5-1  数组说明

        数组的定义和使用需要以下几个步骤:

  • 定义数组

        在C语言中,数组的定义格式为:

数据类型 数组名[数组长度]

        其中,数据类型表示数组中元素的类型,数组名是用来标识数组的名称,数组长度表示数组中元素的个数。

  • 初始化数组

        我们可以在定义数组的同时对数组元素进行初始化,也可以在定义后使用赋值语句进行初始化。

        需注意:大括号{ }之间的值的数目不能大于我们在数组声明时在方括号[ ]中指定的元素数目,即数组元素不能越界。

        下图5-2为在进行数组定义时的几种初始化示例代码。

图5-2  数组定义初始化代码
  • 使用数组

        可以使用下标(索引)来访问数组中的元素。数组的下标从0开始,最大下标为数组长度减1。可参考下图5-3理解数组下标及元素。

图5-3  数组长度和索引

        我们还是以之前的数组numbers为例进行说明。示例代码如下图5-4所示:

图5-4  通过数组下标访问数组元素

        注意:如果数组下标越界的话,会导致访问到未定义的内存区域,可能引发程序崩溃或产生不可预测的结果。

  • 获取数组长度

        可以使用sizeof运算符来获取数组的长度(以字节为单位)。其示例代码见下图5-5。

图5-5  获取数组长度

        在上述代码中,sizeof(numbers)表示数组所占用的总字节数,sizeof(numbers[0])表示数组元素的字节数。通过两者相除,即可得到数组的长度。


5.2 多维数组及其应用

        多维数组是由多个一维数组组成的数据结构。它们可以看作是矩阵或表格。在C语言中,可以使用多维数组来存储和操作多维数据。多维数组的定义格式如下:

dataType arrayName[size1][size2]...[sizeN];

        其中:dataType是数组中元素的数据类型,arrayName是数组的名称,size1、size2、...、sizeN是数组每个维度的大小。

        多维数组的初始化方式与一维数组相似,只是需要嵌套使用大括号来指定每个维度的初始值。多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。例如,下面定义了一个3行4列的整数矩阵(二维数组):

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

        多维数组的元素可以通过使用多个下标来访问。下标的数量和维度数相同,下标从0开始。要访问二维数组中的元素,可以使用类似arrayName[row][col]的语法。见下图5-6。

图5-6  二维数组形式

        因此,数组中的每个元素是使用形式为 a[ i , j ] 的元素名称来标识的,其中 a 是数组名称,i 和 j 是唯一标识 a 中每个元素的下标。例如:要访问二维数组中的第一个元素,我们可以使用 matrix[0][0];要访问第二行第三列的元素,我们可以使用 matrix[1][2]。

        注意:多维数组的内存布局是连续的,即所有元素在内存中是按一维方式存储的。即对于上面的二维数组,实际存储在内存中的方式是按照1, 2, 3, 4, 5, 6, ...的顺序排列的。

        多维数组的应用非常广泛,特别是在处理矩阵、图像和表格数据等方面。通过使用多维数组,可以更方便地存储和操作这些数据。


5.3 静态数组和动态数组

        在 C 语言中,有两种类型的数组:静态数组和动态数组。

1. 静态数组

        静态数组是在编译时声明并分配内存空间的数组。静态数组具有固定的大小,在声明数组时需要指定数组的长度。静态数组的特点包括:

  • 内存分配:在程序编译时,静态数组的内存空间就被分配好了,存储在栈上或者全局数据区。
  • 大小固定:静态数组的大小在声明时确定,并且无法在运行时改变。
  • 生命周期:静态数组的生命周期与其作用域相关。如果在函数内部声明静态数组,其生命周期为整个函数执行期间;如果在函数外部声明静态数组,其生命周期为整个程序的执行期间。

        静态数组的声明和初始化示例:

int staticArray[5]; // 静态数组声明
int staticArray[] = {1, 2, 3, 4, 5}; // 静态数组声明并初始化

        下图5-7是一个简单的静态数组实例:

图5-7  静态数组使用示例

        以上实例中,我们声明并初始化了一个静态数组 staticArray,它包含了5个整数元素,然后我们通过sizeof运算符计算静态数组的长度,并使用循环遍历并打印数组的元素。

2. 动态数组

        动态数组是在运行时通过动态内存分配函数(如malloc和calloc)手动分配内存的数组。动态数组特点如下:

  • 内存分配:动态数组的内存空间在运行时通过动态内存分配函数手动分配,并存储在堆上。需要使用 malloc、calloc 等函数来申请内存,并使用 free 函数来释放内存。
  • 大小可变:动态数组的大小在运行时可以根据需要进行调整。可以使用 realloc 函数来重新分配内存,并改变数组的大小。
  • 生命周期:动态数组的生命周期由程序员控制。在使用动态数组时,需要注意合理地分配内存,使用完数组后需要手动释放内存,以避免内存泄漏和访问无效内存的问题。

        注意:动态数组的使用需要注意内存管理的问题,确保在不再需要使用数组时释放内存,避免内存泄漏和访问无效的内存位置。

下图5-8是一个简单的动态数组使用实例:

图5-8  动态数组使用示例

        以上实例中,我们首先声明了一个变量 size 来指定动态数组的大小。然后使用 malloc 函数为动态数组分配内存,并通过 sizeof 运算符计算所需的内存大小。最后使用循环遍历并打印动态数组的元素。在程序结束时,使用 free 函数释放动态数组所占用的内存。

        注意,在使用动态数组时,需要检查内存分配是否成功(即 arr 是否为 NULL),以避免在内存分配失败时发生错误。


5.4 数组作为参数传递

        在C语言中,数组是一种特殊的数据结构,它可以存储一系列相同类型的数据。当我们需要在函数中使用数组时,可以通过传递数组的地址来实现。

        在函数中传递数组的方式有两种:传递数组的指针或传递数组的副本。下面分别详细说明这两种方式。

1. 传递数组的指针

        通过传递数组的指针,函数可以直接访问原始数组,并对其进行修改。具体操作步骤如下所示:

  • 在函数的参数列表中声明一个指针变量,用于接收数组的地址。
  • 在调用函数时,将数组的名称作为实参传递给函数。
  • 在函数中,可以使用指针来访问数组元素,并对其进行操作。

        示例代码见下图5-9。

图5-9  传递数组的指针

        代码解读:在上面的示例中,我们定义了一个名为modifyArray的函数,它接受一个指针参数arr和一个整数参数size,表示数组的地址和大小。在main函数中,我们定义了一个整型数组array,并计算出数组的大小。然后我们调用modifyArray函数,并将数组array和大小size作为实参传递给它。在modifyArray函数中,我们使用指针arr来访问数组元素,并对其进行操作。

2. 传递数组的副本

        当我们不希望函数对原始数组进行修改时,可以传递数组的副本给函数。具体操作步骤如下所示:

  • 在函数的参数列表中声明一个数组变量,用于接收数组的副本。
  • 在调用函数时,将数组的名称作为实参传递给函数。
  • 在函数中,可以使用数组变量来访问数组元素,但对数组元素的修改不会影响原始数组。

        示例代码见下图5-10。

图5-10  传递数组的副本

        代码解读:在上面的示例中,我们定义了一个名为printArray的函数,它接受一个数组参数arr和一个整数参数size,表示数组的副本和大小。在main函数中,我们定义了一个整型数组array,并计算出数组的大小。然后,我们调用printArray函数,并将数组array和大小size作为实参传递给它。在printArray函数中,我们使用数组arr来访问数组元素,并将其输出。

        在C语言中,可以通过传递数组的地址或传递数组的副本来在函数中使用数组。当需要对原始数组进行修改时,可以传递数组的地址;当不希望对原始数组进行修改时,可以传递数组的副本。


5.5 数组作为返回值返回

        C 语言无法直接返回一个完整的数组作为函数的参数。但是,您可以通过指定不带索引的数组名来返回一个指向数组的指针。另外,C语言不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。因此我们可以通过以下两种常用的方法实现从函数返回数组:

1. 使用静态数组

        在函数内部定义一个静态数组,并在函数结束前将该数组作为返回值返回。静态数组的特点是其生存周期与程序的运行周期一致,所以可以安全地返回。但是,静态数组的大小必须在编译时确定。示例代码见下图5-11。

图5-11  使用静态数组返回

2. 使用动态内存分配

        在函数内部使用malloc函数动态分配一块内存空间,并在函数结束前将指向该内存空间的指针作为返回值返回。这样可以返回一个动态分配的数组,其大小可以在运行时确定。示例代码见下图5-12。

图5-12  使用动态内存返回

        注意:使用动态内存分配后,需要在使用完毕后使用free函数释放已分配的内存空间,以避免内存泄漏问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值