C语言:数组的介绍与使用

1. 数组的概念

数组是⼀组相同类型元素的集合;从这个概念中我们就可以发现2个有价值的信息:
• 数组中存放的是1个或者多个数据,但是数组元素个数不能为0。
• 数组中存放的多个数据,类型是相同的。
数组分为⼀维数组和多维数组,多维数组⼀般⽐较多⻅的是⼆维数组。

2. ⼀维数组的创建和初始化,介绍与使用

2.1 数组创建

⼀维数组创建的基本语法如下:

复制代码
data_type array_name[array_size];
  • data_type:指定数组中元素的数据类型,如 intfloatchar 等。
  • array_name:数组的名称,遵循标识符的命名规则。
  • array_size:数组的大小,即数组中元素的个数,必须是一个大于 0 的常量表达式。
  • 示例:
复制代码
  #include <stdio.h>

  int main() 
  {
      // 定义一个包含 5 个整数的一维数组
      int numbers[5];
      return 0;
  }
2.2 一维数组的初始化
复制代码
  #include <stdio.h>

  int main()
   {
      // 完全初始化
      int arr1[5] = {1, 2, 3, 4, 5};

      // 部分初始化,未指定的元素自动初始化为 0
      int arr2[5] = {1, 2};

      // 省略数组大小,编译器会根据初始化列表的元素个数确定数组大小
      int arr3[] = {1, 2, 3, 4, 5};

      //错误的初始化 - 初始化项太多
      int arr4[3] = {1, 2, 3, 4};

      return 0;
  }
2.3 一维数组元素的访问
复制代码
  #include <stdio.h>

  int main()
   {
      int arr[5] = {1, 2, 3, 4, 5};

      // 访问数组的第一个元素
      printf("数组的第一个元素是:%d\n", arr[0]);

      // 修改数组的第三个元素
      arr[2] = 10;
      printf("修改后的第三个元素是:%d\n", arr[2]);

      return 0;
  }
2.4 数组的类型

数组也是有类型的,数组算是⼀种⾃定义类型,去掉数组名留下的就是数组的类型。
如下:

复制代码
  int arr1[10];
  char ch1[5];

  int arr2[2][5];
  char ch2[2][5];

arr1 数组的类型是 int [10]: 表示这是一个包含 10 个 int 类型元素的数组。 int 是 C 语言中用于表示整数的数据类型,在大多数系统中,一个 int 类型通常占用 4 个字节的内存空间。
ch1 数组的类型是 char [5]: 表示这是一个包含 5 个 char 类型元素的数组。 char 是 C 语言中用于表示字符的数据类型,通常占用 1 个字节的内存空间。
**arr2 数组的类型是 int [2][5]:**表示的是二维数组类型。具体来说,这种类型的数组可以看作是一个具有 2 行 5 列的矩阵结构,数组中的每个元素都是 int 类型(整数类型)。在内存中,这些元素是连续存储的,先存储第一行的 5 个元素,接着存储第二行的 5 个元素。
**ch2 数组的类型是 char [2][5]:**表示的是一个二维字符数组。可以将其想象成一个具有 2 行 5 列的表格,表格中的每个单元格存储一个 char 类型的数据,即一个字符。在 C 语言里, char 类型通常占用 1 个字节的内存空间,所以这个二维数组总共能存储 2 * 5 = 10 个字符。

2.5 ⼀维数组的使⽤

学习了⼀维数组的基本语法,⼀维数组可以存放数据,存放数据的⽬的是对数据的操作,那我们如何使⽤⼀维数组呢?

2.6 数组下标

C语⾔规定数组是有下标的,下标是从0开始的,假设数组有n个元素,最后⼀个元素的下标是n-1,下标就相当于数组元素的编号,如下:

复制代码
  int arr[10] = {5,6,7,8,9,10,11,12,13,14);


数组元素和下标
在C语⾔中数组的访问提供了⼀个操作符 [] ,这个操作符叫:下标引⽤操作符。
有了下标访问操作符,我们就可以轻松的访问到数组的元素了,⽐如我们访问下标为0的元素,我们就 可以使⽤ arr[0] ,想要访问下标是6的元素,就可以使⽤ arr[6] ,如下代码:

复制代码
  #include <stdio.h>
  int main()
  {
  int arr[10] = {5,6,7,8,9,10,11,12,13,14);
   printf("%d\n", arr[0]);//5
   printf("%d\n", arr[6]);//11
  return 0;
  }
2.7 数组元素的打印

接下来,如果想要访问整个数组的内容,那怎么办呢?
只要我们产⽣数组所有元素的下标就可以了,那我们使⽤for循环产⽣0~9的下标,接下来使⽤下标访 问就⾏了。
如下代码:

复制代码
  #include <stdio.h>
  int main()
  {
   int arr[10] = {5,6,7,8,9,10,11,12,13,14);
   int i = 0;
   for(i=0; i<10; i++)
   {
   printf("%d ", arr[i]);
   }
   return 0;
  }
2.8 数组的输⼊

明⽩了数组的访问,当然我们也根据需求,⾃⼰给数组输⼊想要的数据,如下:

复制代码
  #include <stdio.h>
  int main()
  { 
     int arr[10] = {5,6,7,8,9,10,11,12,13,14);
     int i = 0;
     for(i=0; i<10; i++)
    {
       scanf("%d", &arr[i]);
    }
     for(i=0; i<10; i++)
    {
       printf("%d ", arr[i]);
    }
   return 0;
   }
2.9 ⼀维数组在内存中的存储

在 C 语言中,一维数组在内存中的存储是连续的,这意味着数组的各个元素在内存中依次相邻排列。以下从存储方式、内存地址计算、示例代码等方面详细介绍一维数组在内存中的存储情况。

存储方式

一维数组在内存中占据一段连续的内存空间,数组的元素按照其下标顺序依次存储。例如,对于一个包含 n 个元素的一维数组 arr,元素 arr[0] 存储在这段连续内存空间的起始位置,接着是 arr[1]arr[2] ,以此类推,直到 arr[n - 1]

内存地址计算

数组元素的内存地址可以通过数组首地址和元素的偏移量来计算。假设数组 arr 的首地址为 &arr[0](也可以用数组名 arr 表示),每个元素占用的内存字节数为 sizeof(arr[0]),计算总大小可以多少字节为sizeof(arr)。

如:

3. 二维数组的创建和初始化,介绍与使用

前⾯学习的数组被称为⼀维数组,数组的元素都是内置类型的,如果我们把⼀维数组做为数组的元素 ,这时候就是**⼆维数组** ,⼆维数组作为数组元素的数组被称为三维数组,⼆维数组以上的数组统称 为多维数组

3.1 ⼆维数组的创建
复制代码
数据类型 数组名[行数][列数];
  • 数据类型 :指定数组中每个元素的数据类型,例如 intfloatchar 等。

  • 数组名:是用户自定义的标识符,用于标识这个二维数组。

  • 行数:表示二维数组有多少行,必须是一个大于 0 的整数常量表达式。

  • 列数:表示二维数组每行有多少列,同样必须是一个大于 0 的整数常量表达式。

    #include <stdio.h>

    int main()
    {
    // 创建一个 3 行 4 列的二维整数数组
    int matrix[3][4];
    return 0;
    }

在这个例子中,matrix 是一个包含 3 行 4 列的二维数组,总共可以存储 3 * 4 = 12int 类型的元素

3.2 ⼆维数组的初始化
复制代码
#include<stdio.h>
int main()
{    //完全初始化
	int arr[2][3] = { 1,2,3,4,5,6 };
	int arr[2][3] = { {1,2,3},{4,5,6} };

	//部分初始化
	int arr[2][3] = { 1,2,3,4};
	int arr[2][3] = { {1,2,3},{4}};

	//省略行数初始化,但是不能省略列
	int arr[][3] = { 1,2,3,4,5,6 };//省略行数它会根据总大小除于列数计算出行数:6/3=2行
	int arr[][3] = { {1,2,3},{4,5,6} };
	return 0;
}
3.3 ⼆维数组的下标

当我们掌握了⼆维数组的创建和初始化,那我们怎么使⽤⼆维数组呢?
其实⼆维数组访问也是使⽤下标的形式的,⼆维数组是有⾏和列的,只要锁定了⾏和列就能唯⼀锁定数组中的⼀个元素。
C语⾔规定,⼆维数组的⾏是从0开始的,列也是从0开始的,如下所⽰:

复制代码
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};


图中最右侧绿⾊的数字表⽰⾏号,第⼀⾏蓝⾊的数字表⽰列号,都是从0开始的,⽐如,我们说:第2⾏,第4列,快速就能定位出7。

复制代码
#include <stdio.h>
int main()
{
 int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
 printf("%d\n", arr[2][4]);
return 0;
}
3.4 ⼆维数组的输⼊和输出

访问⼆维数组的单个元素我们知道了,那如何访问整个⼆维数组呢?
其实我们只要能够按照⼀定的规律产⽣所有的⾏和列的数字就⾏;以上⼀段代码中的arr数组为例,⾏的选择范围是0~2,列的取值范围是0~4,所以我们可以借助循环实现⽣成所有的下标。

复制代码
#include <stdio.h>
int main()
{
 int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
 int i = 0;//遍历⾏
 //输⼊
 for(i=0; i<3; i++) //产⽣⾏号
 {
 int j = 0;
 for(j=0; j<5; j++) //产⽣列号
 {
 scanf("%d", &arr[i][j]); //输⼊数据
 }
 }
 //输出
 for(i=0; i<3; i++) //产⽣⾏号
 {
 int j = 0;
 for(j=0; j<5; j++) //产⽣列号
 {
 printf("%d ", arr[i][j]); //输出数据
 }
 printf("\n");
 }
 return 0;
}
3.5 ⼆维数组在内存中的存储

存储方式:按行连续存储

二维数组在内存中是按行连续存储的。也就是说,二维数组先将第一行的所有元素依次存储在内存中,接着存储第二行的元素,以此类推,直到存储完所有行的元素。这种存储方式使得二维数组在内存中实际上是一个线性的连续内存块。

地址计算
二维数组元素的内存地址可以通过数组首地址和元素的偏移量来计算。假设二维数组 arr[m][n] 的首地址为 &arr[0][0](也可以用数组名 arr 表示),每个元素占用的内存字节数为 sizeof(arr[0][0]),那么数组中第 i 行第 j 列的元素 arr[i][j] 的内存地址可以通过以下公式计算:

复制代码
&arr[i][j] = &arr[0][0] + (i * n + j) * sizeof(arr[0][0])

其中,i * n 表示前面 i 行元素的总数,再加上 j 就是从数组首元素到 arr[i][j] 的偏移量。

注意事项
  • 内存连续性:二维数组元素的内存连续性使得可以通过指针运算来访问数组元素,但同时也要求在操作数组时要注意避免越界访问,否则可能会访问到相邻的其他变量或数据,导致未定义行为。
  • 列数的重要性:在进行地址计算和指针操作时,列数是一个关键因素,因为编译器需要根据列数来正确计算元素的偏移量。
  • 与多维数组的关系:二维数组的存储方式可以推广到更高维的数组,多维数组同样是按行优先的顺序在内存中连续存储。

4. C99中的变⻓数组

在C99标准之前,C语⾔在创建数组的时候,数组⼤⼩的指定只能使⽤常量、常量表达式,或者如果我们初始化数据的话,可以省略数组⼤⼩。

复制代码
int arr1[10];
int arr2[3+5];
int arr3[] = {1,2,3};

这样的语法限制,让我们创建数组就不够灵活,有时候数组⼤了浪费空间,有时候数组⼜⼩了不够⽤的。
C99中给⼀个变⻓数组(variable-length array,简称 VLA)的新特性,允许我们可以使⽤变量指定
数组⼤⼩。
请看下⾯的代码:

复制代码
int n = a+b;
int arr[n];

上⾯⽰例中,数组 arr 就是变⻓数组,因为它的⻓度取决于变量 n 的值,编译器没法事先确定,只
有运⾏时才能知道 n 是多少。
变⻓数组的根本特征,就是数组⻓度只有运⾏时才能确定,所以 变⻓数组不能初始化 。它的好处是程序员不必在开发时,随意为数组指定⼀个估计的⻓度,程序可以在运⾏时为数组分配精确的⻓度。有 ⼀个⽐较迷惑的点,变⻓数组的意思是数组的⼤⼩是可以使⽤变量来指定的,在程序运⾏的时候,根 据变量的⼤⼩来指定数组的元素个数,⽽不是说数组的⼤⼩是可变的数组的⼤⼩⼀旦确定就不能再 变化了(在程序运行时确定,就不能修改,直到程序结束)
遗憾的是在VS2022上,虽然⽀持⼤部分C99的语法,没有⽀持C99中的变⻓数组,没法测试;下⾯是 我在gcc编译器上测试,可以看⼀下
如:

复制代码
#include <stdio.h>
int main()
{
 int n = 0;
 scanf("%d", &n);//通过键盘输⼊数值确定数组的⼤⼩
 int arr[n];
 int i = 0;
 for (i = 0; i < n; i++)
 {
 scanf("%d", &arr[i]);
 }
 for (i = 0; i < n; i++)
 {
 printf("%d ", arr[i]);
 }
 return 0;
}

以上就是数组的全部介绍了。

相关推荐
沐怡旸14 小时前
【算法】【链表】328.奇偶链表--通俗讲解
算法·面试
掘金安东尼17 小时前
Amazon Lambda + API Gateway 实战,无服务器架构入门
算法·架构
码流之上17 小时前
【一看就会一写就废 指间算法】设计电子表格 —— 哈希表、字符串处理
javascript·算法
用户61204149221318 小时前
C语言做的文本词频数量统计功能
c语言·后端·敏捷开发
快手技术19 小时前
快手提出端到端生成式搜索框架 OneSearch,让搜索“一步到位”!
算法
CoovallyAIHub2 天前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
NAGNIP2 天前
Serverless 架构下的大模型框架落地实践
算法·架构
moonlifesudo2 天前
半开区间和开区间的两个二分模版
算法
moonlifesudo2 天前
300:最长递增子序列
算法
CoovallyAIHub2 天前
港大&字节重磅发布DanceGRPO:突破视觉生成RLHF瓶颈,多项任务性能提升超180%!
深度学习·算法·计算机视觉