C语言基础学习记录-数组

1.数组的概念

数组(Array):是多个相同类型数据,按照一定顺序排列的集合,并使用一个名字命名,并通过编号方式对这些数据进行统一管理。

  • 数组是 C 语言中的一种数据结构,用于存储一组具有相同数据类型的数据
  • 数组中的每个元素可以通过一个索引(下标)来访问,索引从 0 开始,最大值为数组长度减 1
  • 数组是若干个相同类型的变量在内存中有序存储的集合。

2.数组的特点

  • 数组中的元素在内存中是依次紧密排列的,有序的。
  • 创建数组对象会在内存中开辟一整块连续的空间。占据的空间大小,取决于数组的长度和数组中元素的类型
  • 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
  • 数组,一旦初始化完成,其长度就是确定的。数组的长度一旦确定就不能修改。
  • 数组名中引用的是这块连续空间的首地址

 3.一维数组的定义

定义数组的语法格式:

类型 数组名[元素个数];

int arr[10];// 数组 arr ,里面包含10个成员,每个成员都是int 类型

或者         #define NUM 10

                int arr1[NUM];

注意:声明数组时,必须给出数组的大小。
  • 数组名不能与其他变量名相同,同一作用域内是唯一的
  • 其下标从0开始,因此5个元素分别为arr[0] arr[1] arr[2] arr[3] arr[4]

 

注意:数组角标越界:

假设数组有n个元素,如果使用的数组的下标小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间访问。

C语言不做数组下标越界的检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确。

 4.数组内存分析

数组名,记录数组的首地址,即a[0]的地址

数组的各个元素是连续分布的,假如a[0] 地址是0x1122, 则 a[1]的地址=a[0]的地址+int字节数a[1]=0x1126,后面依次类推

注意事项:

c语言规则,数组变量一旦声明,数组名指向的地址就不可更改。因为声明数组时,编译器会自动为数组分配内存地址,这个地址与数组名是绑定的,不可更改。

因此,当数组定义后,再用大括号重新赋值,是不允许的。下面的代码会报错。

5.变长数组

变长数组的根本特征是数组长度只有运行时才能确定 。它的好处是程序员不必在开发时,随意为数组指定一个估计的长度,程序员可以运行时为数组分配精确的长度。

以前的方法是一但定义后就不能改变,要想根据需要处理更多的数据。可以使用以下的方法

动态内存分配:使用malloc、calloc或realloc等函数来动态地分配和重新分配内存。

这允许你在运行时改变内存块(可以看作是一个动态数组)的大小

 C库函数<stdlib.h>

        size_t是 stdlib.h 中定义的变量类型:
        这是无符号整数类型,它是 sizeof 关键字的结果。

 void *malloc(size_t size) 

分配所需的内存空间,并返回一个指向它的指针。

描述

C 库函数 void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。

声明

下面是 malloc() 函数的声明。

void *malloc(size_t size)

参数

  • size -- 内存块的大小,以字节为单位。

返回值

该函数返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL。

void *calloc(size_t nitems, size_t size)

描述

C 库函数 void *calloc(size_t nitems, size_t size) 分配所需的内存空间,并返回一个指向它的指针。malloc 和 calloc 之间的不同点是,malloc 不会设置内存为零,而 calloc 会设置分配的内存为零。

注意:calloc() 函数将分配的内存全部初始化为零。如果不需要初始化,可以使用 malloc() 函数代替。另外,使用 calloc() 函数时需要注意,如果分配的内存块过大,可能会导致内存不足的问题。

声明

下面是 calloc() 函数的声明。

void *calloc(size_t nitems, size_t size)

参数

  • nitems -- 要被分配的元素个数。
  • size -- 元素的大小。

返回值

该函数返回一个指针,指向已分配的内存。如果请求失败,则返回 NULL

realloc()

是 C 标准库中的一个函数,用于重新分配内存空间。它在动态内存管理中非常重要,尤其是在需要调整已分配内存大小的情况下。

C 库函数 void *realloc(void *ptr, size_t size) 尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小。

声明

下面是 realloc() 函数的声明:

void *realloc(void *ptr, size_t size)

参数

  • ptr -- 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。
  • size -- 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。

返回值

  • 如果成功,realloc() 返回指向新内存块的指针。
  • 如果失败,返回 NULL,并且原来的内存块仍然保持不变(并没有释放)。

使用说明

  • realloc() 可能会将内存块移动到新的位置(如果在原位置没有足够的空间容纳新的大小)。如果移动成功,ptr 会指向新位置。需要特别注意,旧的 ptr 指针需要被更新为 realloc() 返回的新地址。
  • 如果内存分配失败,realloc() 返回 NULL,而原始的内存块不会被释放。为避免内存泄漏,应该使用一个临时指针来接收 realloc() 的返回值,并检查是否为 NULL

free()

描述

在 C 语言中,free() 函数是标准库函数,用于释放由 malloc()calloc()realloc() 等动态分配函数分配的内存。当动态分配的内存不再需要时,调用 free() 函数可以避免内存泄漏,确保程序有效地管理内存。

声明

下面是 free() 函数的声明。

void free(void *ptr)

参数

  • ptr -- 指针指向一个要释放内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果传递的参数是一个空指针,则不会执行任何动作。

返回值

该函数不返回任何值。

6.数组的复制

由于数组名是指针,所以复制数组不能简单地复制数组名。

int a[3]={10,20,30};

int *b;

b=a;

不是将数组a复制给数组b,而是让a和b指向同一个数组

数组的复制只能使用 

  • 循环的方法

  • 用memcpy函数

void *memcpy(void *str1, const void *str2, size_t n)

描述

C 库函数(string.h) void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1

声明

下面是 memcpy() 函数的声明。

void *memcpy(void *str1, const void *str2, size_t n)

参数

  • str1 -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
  • str2 -- 指向要复制的数据源,类型强制转换为 void* 指针。
  • n -- 要被复制的字节数。

返回值

该函数返回一个指向目标存储区 str1 的指针。

 

两种方式对比: 

1. 循环复制:

优点: 简单直观,容易理解和实现。不需要引入额外的头文件。

缺点:需要编写循环代码来遍历数组并逐个赋值,相对而言可能稍显繁琐。不适用于复制大型数组或复杂数据结构。

2.memery函数复制:

优点:使用标准库提供的函数,可以实现快速且高效的内存复制。适用于大型数组或复杂的数据结构的复制。可以直接复制字节数,不需要遍历数组。

缺点:需要包含头文 件,对于简单的数组复制,可能有些过于繁重。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值