前言
在学习数据结构时,我们最先接触的便是动态数组,本文将手把手带你用C语言实现动态数组。
具体实现
定义结构体
typedef struct
{
int* array;
size_t size;
} dynamic_array;
- 结构体内部包含两个成员:
int* array
:一个指向整型数组的指针。这意味着动态数组实际存储的是一个整数数组的地址,通过这个指针可以访问和操作数组中的元素。size_t size
:一个无符号整数类型变量,通常用于表示数组当前的实际大小或容量,即数组中可用元素的数量。
通过使用这个结构体,可以创建并管理一个可变长度的整数数组,可以在运行时根据需要动态地改变其大小。在后续的函数实现中(如 create_array()
、read_array()
等),会利用这两个成员来分配、读取和释放内存空间等操作。
用于创建动态数组的函数 Function to create a new dynamic array
dynamic_array* create_array(size_t size)
{
dynamic_array* arr = malloc(sizeof(dynamic_array));
if (arr == NULL)
{
printf("Error: Failed to allocate memory for dynamic array structure.\n");
return NULL;
}
arr->array = malloc(size * sizeof(int));
if (arr->array == NULL)
{
printf("Error: Failed to allocate memory for the internal integer array.\n");
free(arr);
return NULL;
}
arr->size = size;
return arr;
}
基础知识解读
->
在C语言中,->
运算符用于访问结构体或联合体类型的指针所指向的成员。它等价于解引用指针后通过.
运算符来访问成员。
具体到 arr->array = malloc(size * sizeof(int));
这行代码:
arr
是一个指向dynamic_array
结构体类型的指针。->
运算符用于访问arr
指向的结构体实例中的成员变量array
。- 也就是说,这行代码为
arr
所指向的dynamic_array
结构体的array
成员分配内存空间。通常情况下,array
成员是一个指向整数数组的指针,这里根据传入的size
参数动态分配了足够存储size
个整数的空间。
简而言之,arr->array
相当于 (arr).array
,即先通过指针 arr
访问到 dynamic_array
结构体对象,然后在这个结构体对象内部找到并操作 array
成员。
malloc
malloc
是C语言的动态内存分配函数,它从堆上分配指定大小的连续内存空间,并返回指向这块内存区域的指针。如果分配成功,则返回非空指针;否则(例如,当系统内存不足时),返回NULL
定义了一个名为 create_array
的函数,用于创建一个指定大小的动态数组。
函数接受一个 size_t
类型参数 size
,表示要创建的整数数组的元素个数。
具体步骤如下:
- 调用
malloc(sizeof(dynamic_array))
函数分配足够存储dynamic_array
结构体的内存空间,并将返回的内存地址赋给指向该结构体类型的指针arr
。 - 为
dynamic_array
结构体中的array
成员分配内存,调用malloc(size * sizeof(int))
分配能够存储size
个整数的空间。这里的sizeof(int)
获取的是每个整数在当前系统上占用的字节数。然后将新分配的内存地址赋给arr->array
,即为动态数组的内部整数数组分配了内存。 - 将传入的参数
size
赋给arr->size
,记录动态数组的实际容量(即可以存储多少个整数)。 - 最后,函数返回指向新创建的
dynamic_array
结构体的指针arr
,这样调用者就可以通过这个指针操作和访问这个动态数组了。
用于读取动态数组元素的函数Function to read an element from a dynamic array
int read_array(dynamic_array* arr, size_t index) {
if (index < arr->size)
return arr->array[index];
else
{
printf("Error: index out of bounds: %d\n", index);
return -1;
}
}
这段代码定义了一个名为 read_array
的函数,用于从动态数组中读取指定索引处的整数值。函数接受两个参数:
dynamic_array* arr
:指向动态数组结构体的指针。size_t index
:要读取的元素在数组中的索引位置。
函数执行流程如下:
- 首先检查传入的索引值(
index
)是否小于动态数组的大小(arr->size
)。如果索引有效(即index < arr->size
),则返回数组中对应索引位置的整数值,通过表达式arr->array[index]
访问。 - 如果索引超出数组边界(即
index >= arr->size
),函数会输出错误信息"Error: index out of bounds: %d\n"
,其中%d
会被替换为实际的非法索引值,并返回一个特殊值-1
,表示读取失败或异常情况。
该函数提供了安全访问动态数组元素的方法,同时也确保了当尝试访问不存在的元素时能够提供明确的错误反馈。
用于更新动态数组元素的函数Function to update an element from a dynamic array
void update_array(dynamic_array* arr, size_t index, int value) {
if (index < arr->size)
arr->array[index] = value;
else
printf("Error: index out of bounds: %d\n", index);
}
这段代码定义了一个名为 update_array
的函数,其功能是更新动态数组中指定索引位置的元素值。该函数接受三个参数:
dynamic_array* arr
:指向动态数组结构体的指针。size_t index
:要更新的元素在数组中的索引位置。int value
:新值,将用于替换原数组中对应索引位置的值。
函数执行过程如下:
- 首先检查传入的索引值(
index
)是否小于动态数组的大小(arr->size
)。如果索引有效(即index < arr->size
),则将整数value
赋给数组中对应索引位置的元素,通过表达式arr->array[index] = value
完成更新操作。 - 如果索引超出数组边界(即
index >= arr->size
),函数会输出错误信息"Error: index out of bounds: %d\n"
,其中%d
会被替换为实际的非法索引值。但此处与read_array
函数不同,它没有返回任何值,仅输出错误信息,不会改变数组的状态。
此函数提供了对动态数组元素进行安全更新的能力,并在尝试访问不存在的元素时给出错误提示。
用于删除动态数组的函数Function to delete a dynamic array
这段代码定义了一个名为 delete_array
的函数,用于释放动态数组占用的内存资源并确保后续不再使用已释放的指针。该函数接受一个参数:
dynamic_array* arr
:指向动态数组结构体的指针。
函数执行过程如下:
-
首先调用
free(arr->array)
来释放动态数组内部整数数组所占用的内存空间,并将arr->array
设置为NULL
。这样可以防止程序后续尝试访问已释放的内存区域,从而避免潜在的未定义行为或错误。 -
接着调用
free(arr)
释放整个动态数组结构体(包括其成员变量size
)占用的内存空间。 -
最后,将
arr
指针本身设置为NULL
。虽然这个操作不会改变传入函数的实际参数值(因为C语言中传递的是指针副本),但在某些情况下,特别是在单个作用域内需要确保指针在释放内存后不会被误用时,这是一个良好的编程实践。它能够明确地表明该指针当前不再指向有效数据,并且有助于调试和减少因误用已释放指针导致的问题。
需要注意的是,在实际编程中,尽管在函数内部将 arr
设置为 NULL
对于函数外部的影响有限,但这种做法可以增强代码的可读性和防御性编程水平。
Main函数
int main() {
dynamic_array* arr = create_array(10);
update_array(arr,6,99);
int value = read_array(arr, 6);
printf("The value is: %d \n", value);
delete_array(arr);
}
这段代码是 main()
函数的实现,用于演示如何创建、操作和销毁动态数组。
-
首先调用
create_array(10)
函数,创建一个可以存储10个整数的动态数组,并将其地址赋值给指针变量arr
。 -
接着通过调用
update_array(arr, 6, 99)
函数,在动态数组中索引为6的位置处更新元素值为99。这里假设数组索引从0开始计数,因此第6个位置实际上是在数组中的第7个元素(因为数组下标是从0开始)。 -
调用
read_array(arr, 6)
函数,从动态数组中读取索引为6的位置处的整数值,并将该值存储在变量value
中。 -
使用
printf("The value is: %d \n", value);
输出刚刚读取到的整数值,显示更新后的数组元素内容。 -
最后,调用
delete_array(arr)
函数来释放之前分配给动态数组的所有内存资源,完成对动态数组的生命周期管理。
总结
#include<stdio.h>
#include<stdlib.h>
//Define a dynamic array structure that stores an array and its size
typedef struct
{
int* array;
size_t size;
}dynamic_array;
//Function to create a new dynamic array
dynamic_array* create_array(size_t size)
{
dynamic_array* arr = malloc(sizeof(dynamic_array));
if (arr == NULL)
{
printf("Error: Failed to allocate memory for dynamic array structure.\n");
return NULL;
}
arr->array = malloc(size * sizeof(int));
if (arr->array == NULL)
{
printf("Error: Failed to allocate memory for the internal integer array.\n");
free(arr);
return NULL;
}
arr->size = size;
return arr;
}
//Function to read an element from a dynamic array
int read_array(dynamic_array* arr, size_t index) {
if (index < arr->size)
return arr->array[index];
else
{
printf("Error: index out of bounds: %d\n", index);
return -1;
}
}
//Function to update an element from a dynamic array
void update_array(dynamic_array* arr, size_t index, int value) {
if (index < arr->size)
arr->array[index] = value;
else
printf("Error: index out of bounds: %d\n", index);
}
//Function to delete a dynamic array
void delete_array(dynamic_array* arr) {
free(arr->array);
arr->array = NULL;
free(arr);
arr = NULL;
}
//main
int main() {
dynamic_array* arr = create_array(10);
update_array(arr,6,99);
int value = read_array(arr, 6);
printf("The value is: %d \n", value);
delete_array(arr);
return 0;
}
该源码来自B站up Micro_Frank