C语言基础内容(四)——第04章_数组

发布时间:2024年01月12日

第04章_数组

本章专题脉络

在这里插入图片描述

1、数组的概述

1.1 为什么需要数组(容器)

  • **生活中的容器:**水杯(装水等液体),衣柜(装衣服等物品),集装箱(装货物等)。
  • **程序中的容器:**将多个数据存储到一起,每个数据称为该容器的元素。

1.2 数组的概念

  • 数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
  • 数组中的概念
    • 数组名
    • 下标(或索引、index)
    • 元素
    • 数组的长度

数组的特点:

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

1.3 数组的分类

按照数组维度分:

  • 一维数组:存储一组数据
  • 二维数组:存储多组数据,相当于二维表,一行代表一组数据。每一行长度可以不同。
  • 三维数组、四维数组、…

按照元素的数据类型分:

  • int类型数组
  • char类型数组
  • double类型数组

2、一维数组的定义

2.1 数组的定义方式1

数组通过变量名后加方括号表示,方括号里面是数组可以容纳的成员数量(即长度)。

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

注意,声明数组时,必须给出数组的大小。

在这里插入图片描述

2.2 数组元素的调用

  • 格式:数组名[下标]
  • 数组的下标从0开始,用“int arr[10];”定义数组,则最大下标值为9,不存在数组元素arr[10]。
arr[0] = 13;       //对该位置数组元素进行赋值
int score = arr[0]; //调用此位置的元素值

数组角标越界:

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

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

int scores[20];
scores[20] = 51;

说明:数组 scores 只有20个成员,因此 scores[20] 这个位置是不存在的。但是,引用这个位置并不会报错。赋值操作会导致紧跟在 scores 后面的那块内存区域被赋值(这实际是其它变量的区域),因此不知不觉就更改了其它变量的值。这很容易引发错误,而且难以发现。

2.3 关于长度

数组的字节长度

sizeof 运算符会返回整个数组的字节长度。

int arr[10];
printf("数组的字节长度为:%zd\n",sizeof(arr)); //40(一个int占4个字节)

数组的长度

在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。

由于数组成员都是同一个类型,每个成员的字节长度都是一样的,所以数组整体的字节长度除以某个数组元素的字节长度,就可以得到数组的成员数量。

//数组中元素的个数:
int arrLen = sizeof(arr) / sizeof(arr[0]);
int a[10];
printf("数组的字节长度为:%zu\n", sizeof(a));   // 40
printf("数组每个元素的字节长度为:%zu\n", sizeof(int)); // 4
printf("数组的长度为:%zu\n", sizeof(a) / sizeof(int)); // 10

复习: sizeof 返回值的数据类型是 size_t ,所以 sizeof(a) / sizeof(a[0]) 的数据类型也是size_t 。在 printf() 里面的占位符,要用 %zd 或 %zu 。

注意:数组一旦声明/定义了,其长度就固定了,不能动态变化

2.4 数组的遍历

将数组中的每个元素分别获取出来,就是遍历。for循环与数组的遍历是绝配。

举例:声明长度为10的int类型数组,给数组元素依次赋值为0,1,2,3,4,5,6,7,8,9,并遍历数组所有元素

int main() {
   

    int arr[10];
    
    //给数组中的每个元素赋值
    for (int i = 0; i < sizeof(arr)/sizeof(int); i++) {
    //对数组元素arr[0]~arr[9]赋值
        arr[i] = i;
    }
    //遍历数组中的元素
    printf("遍历数组中的元素:\n");
    for (int i = 0; i < sizeof(arr)/sizeof(int); i++) {
    //输出arr[0]~arr[9]共10个数组元素
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

2.5 数组的其它定义方式

定义方式2:(定义方式1在2.1节讲的)

数组可以在声明时,使用大括号,同时对每一个成员赋值。

int arr[5] = {
   22, 37, 90, 48, 95};

变形形式1:C 语言允许省略方括号里面的数组成员数量,这时根据大括号里面的值的数量,自动确定数组的长度。

int arr[3] = {
   10,20,30};
// 等同于
int arr[] = {
   10,20,30};  //数组 arr 的长度,将根据大括号里面的值的数量,确定为 3

变形形式2:

对数组部分元素赋初值:如果大括号里面的值,少于数组的成员数量,那么未赋值的成员自动初始化为 0 。

int arr[5] = {
   10, 20, 30};
// 等同于
int arr[5] = {
   10,20,30, 0, 0};

变形方式3

将整个数组的每一个成员都设置为零,最简单的方式如下

int a[100] = {
   0};

错误方式:

使用大括号赋值时,大括号里面的值不能多于数组的长度,否则编译时会报错。

int arr[3] = {
   1,2,3,4};  // 报错

**定义方式3:**数组初始化时,可以指定为哪些位置的成员赋值。

int arr[15] = {
   [2] = 10, [5] = 20, [14] = 30};  //非角标2、5、14的位置自动赋值为0

//等同于
int arr[15] = {
   [5] = 20, [14] = 30, [2] = 10}; //指定位置的赋值可以不按角标从小到大的顺序

变形形式1:指定位置的赋值与顺序赋值,可以结合使用。

int arr[15] = {
   1, [5] = 10, 11, [10] = 20, 21}; //角标0、5、6、10、11的位置被赋值

变形形式2:省略成员数量时,如果同时采用指定位置的赋值,那么数组长度将是最大的指定位置再加1。

int arr[] = {
   [2] = 6, [9] = 12};  //此时数组的长度是10

3、一维数组内存分析

3.1 数组内存图

针对于如下代码:

int a[5] = {
   1,2,3,4,5};

对应的内存结构:
在这里插入图片描述说明:

1)数组名,记录该数组的首地址 ,即 a[0]的地址。

2)数组的各个元素是连续分布的, 假如 a[0] 地址是0x1122,则a[1]地址= a[0]的地址+int字节数(4) = 0x1122

文章来源:https://blog.csdn.net/sun7_9/article/details/135440355
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。