欢迎大家来到贝蒂大讲堂

养成好习惯,先赞后看哦~

所属专栏:C语言学习

贝蒂的主页:Betty‘s blog

引言

前面贝蒂给大家介绍了选择结构与循环结构,今天,贝蒂准备给大家介绍C语言中一个非常重要的结构——数组

1. 数组的定义

数组到底是什么呢,顾名思义就是很多数的集合,其大致满足下面两个条件:

  1. 这些数的类型必须相同。

  2. 这些数在内存中必须是连续存储的。

  • 换句话说,数组就是在内存中连续存储的具有相同类型的一组数据的集合。
  • 数组分为⼀维数组多维数组,多维数组⼀般⽐较多⻅的是⼆维数组。

2. 一维数组

2.1创建与初始化

(1) 创建

一维数组的定义方式如下:

类型说明符 数组名[常量表达式];

  1. 类型说明符就是我们常用的存储类型(char int float double....),当然也可以自定义类型。

  2. 数组名就是我们为其取的名字,最好简单易懂,方便别人阅读。

  3. [] 中的常量值是⽤来指定数组的⼤⼩的,这个数组的⼤⼩是根据实际的需求指定就⾏

  • 注意:在C99之后C语言语法是支持变长数组的,即[]中可以是未知数,但是VS2022编译器是不支持的。

例如:

int arr[5];//表示此时数组arr中有 5 个元素,每个元素都是 int 型变量
char arr2[6];
float arr3[7];
double arr4[1 + 4];//也可以是一个表达式

(2) 初始化

有时候,数组在创建的时候,我们需要给定⼀些初始值,这种就称为初始化。那数组如何初始化呢?数组的初始化⼀般使⽤⼤括号,将需要初始化的数据放在⼤括号中。

初始化分为两种:完全初始化不完全初始化

int arr1[4] = { 1,2,3,4 };//完全初始化
int arr2[4] = { 1,2,3 };//不完全初始化,剩余元素默认为0
char arr3[10] = "hello ";//初始化字符串
int arr4[];//错误初始化

  • 如果进行初始化,可以不在[]声明有几个元素,数组会默认初始化几个元素,数组大小就是几个元素,但是不初始化就一定要声明有几个元素,否则就会报错。

2.2 数组输入和输出

(1) 数组下标

C语⾔规定数组是有下标的,下标是从0开始的(而不是1),假设数组有n个元素,最后⼀个元素的下标是n-1,例如:int arr[10]={1,2,3,4,5,6,7,8,9,10},其下标如下图所示:

arr 1 2 3 4 5 6 7 8 9 10
下标 0 1 2 3 4 5 6 7 8 9

(2) 输入

其实数组输入和我们平常输入差不多,只是输入对象换成了数组。

int main()
{
int arr[10];
int i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", &arr[i]);//循环像数组中输入元素
}
return 0;
}

(3) 输出

输出也是同理,我们可以利用循环输出其数组的每一个元素。

int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);//循环输出
}
return 0;
}

2.3 数组的内存存储

(1) 数组名

C语言规定数组名表示首元素地址,也就是说arr==&arr[0],我们可以通过以下代码来证明:

int main()
{
int arr[2] = { 1,2 };
if (arr == &arr[0])
{
printf("地址相同\n");
}
else
{
printf("地址不相同");
}
return 0;
}

(2) 数组元素的存储

我们知道了数组名表示首元素的地址之后,那么接下来我们可以探究数组每个元素在内存中又是怎样存储的呢,我们将其每个元素的地址打印出观察。

#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i < 10; i++)
{
printf(" &arr[%d] = %p\n ", i, &arr[i]);
}
return 0;
}

输出结果:

从上述地址观察,地址是由⼩到⼤变化的,90,94,98......每次的增量是4,并且我们发现每两个相邻的元素之间相差4(因为⼀个整型是4个字节),就可以很容易得出结论:数组在内存中存储是连续的,理解到这一点,就能为以后指针的学习打好基础。

arr 1 2 3 4 5 6 7 8 9 10
下标 0 1 2 3 4 5 6 7 8 9

2.4 一维数组例题

题目:求任意十个整数的和与平均数。

思路:我们可以先将十个数输入一个数组中,然后循环求其和,在求平均数。

  • 注意:虽然是是个整数,但是最后结果可能是浮点数。

代码参考如下:

int main()
{
int arr[10];
int i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", &arr[i]);//循环输入
}
int sum = 0;//和
for (i = 0; i < 10; i++)
{
sum += arr[i];
}
float avr = sum / 10.0;
printf("这十个数和为%d平均数为%.1f", sum,avr);
return 0;
}

3. 二维数组

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

3.1 创建与初始化

(1) 创建

二维数组定义的一般形式为:

  1. 类型说明符 数组名[ 常量表达式][ 常量表达式];
  • 类比一维数组的定义,只不过二维数组第一个常量表达式表示行,第二个常量表达式表示列

例如:

int arr[5][5];//创建五行五列的二维数组
char arr2[3][5];//字符型二维数组
float arr3[4][5];//浮点型二维数组

(2) 初始化

二维数组的初始化和一维数组的初始化类似,像⼀维数组⼀样,也是使⽤⼤括号初始化的。

int arr1[3][3] = { 1,2 };//不完全初识化

示意图:

1 2 0
0 0 0
0 0 0
  • 不完全初始化剩下元素默认初始化为0。
int arr2[3][3] = { 1,2,3,4,5,6,7,8,9 };//完全初始化

示意图:

1 2 3
4 5 6
7 8 9
int arr3[3][3] = { {1,2},{2,3} };//按照行初始化

示意图:

1 2 0
2 3 0
0 0 0
  • 按行初始化,剩下未初始化的元素默认为0.
int arr4[][3] = { 1,2,3 };//省略行

​ 示意图:

1 2 3
int arr5[3][];//错误初始化
int arr6[][];//错误初始化
  • 二维数组规定只能省略行,不能省略列。

3.2数组的输入和输出

(1) 数组下标

⼆维数组访问和一维数组类似,也是使⽤下标的形式的,⼆维数组是有⾏和列的,只要锁定了⾏和列就能唯⼀锁定数组中的⼀个元素。C语⾔规定,⼆维数组的⾏是从0开始的,列也是从0开始的,例如:int arr[3][3]={1,2,3,4,5,6,7,8,9,10};

示意图:

行/列 0 1 2
0 1 2 3
1 4 5 6
2 7 8 9

(2) 输入

分别循环输入行和列,思路大致和输入一维数组相同。

int main()
{
int arr[3][3] = {0};
int i = 0;
for (i = 0; i < 3; i++)//输入行
{
int j = 0;
for (j = 0; j < 3; j++)//输入列
{
scanf("%d", &arr[i][j]);
}
}
return 0; }

(3) 输出

输出自然也与一维数组大致相同,利用循环依次输出。

int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");//输出一行后换行
}
return 0;
}

3.3 二维数组的存储

(1) 数组名

二维数组的数组名也是一个地址,那和一维数组的数组名有何不同呢,其实二维数组的数组名表示的是第一行的地址,但可能大家还是有下面的疑惑:

int main()
{
int arr[3][3] = { 0 };
printf("%p,%p\n", arr,&arr[0][0]);
return 0;
}

为什么明明二维数组名代表的是第一行的地址,那么为什么和第一个元素的地址相同呢,其实和字符串的存储一样,如果将所有地址表示出来,太浪费内存,而数组在内存中是连续存储的,所以找到首元素的地址,就能找到一行中所有元素的地址。所以就以首元素地址代表第一行的地址

(2) 二维数组元素的存储

像⼀维数组⼀样,我们如果想研究⼆维数组在内存中的存储⽅式,我们也是可以打印出数组所有元素的地址的。代码如下:

int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 3; j++)
{
printf("arr[%d][%d]=%p ",i,j, &arr[i][j]);
}
printf("\n");//输出一行后换行
}
return 0;
}

​ 输出如下:

通过对上面地址的观察,我们知道二维数组也是在内存中连续存储的,并且arr[0][2]和arr[1][0]的地址之间也差4个字节(byte),所以内存存储如下:

arr 1 2 3 4 5 6 7 8 9
下标 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2

3.4 二维数组例题

题目:输入六个数到2行3列的二维数组arr中, 将二维数组arr1中的数组元素转置,即行列互换,存储到3行2列的二维数组arr2中,输出二维数组arr2中的数组元素。

思路:就是循环输入,在转置(行与列交换),最后输出。

代码如下:

int main()
{
int arr1[2][3];
int arr2[3][2];
int i = 0;
int j = 0;
for (i = 0; i < 2; i++)
{
for (j = 0; j < 3; j++)
{
scanf("%d", & arr1[i][j]);
}
}
for (i = 0; i < 2; i++)
{
for (j = 0; j < 3; j++)
{
arr2[j][i] = arr1[i][j];//转置
}
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
printf("%d ", arr2[i][j]);
}
printf("\n");
}
return 0;
}

4. 变长数组

4.1概 念

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

例如:

int arr1[10];
char arr2[4];
int arr3[] = {1,2,3};
  • 但是这样的语法限制,让我们创建数组就不够灵活,有时候数组⼤了浪费空间,有时候数组⼜⼩了不够⽤,所以在C99中给⼀个变⻓数组(variable-length array,简称VLA)的新特性,允许我们可以使⽤变量指定数组⼤⼩

4.2用法

例如:

int n;
scanf("%d",&n);
int arr1[n];
  • 变⻓数组的根本特征,就是数组⻓度只有运⾏时才能确定,所以变⻓数组不能初始化。

探秘C语言数组:解锁高效数据管理与多维空间编程技巧"的更多相关文章

  1. GO语言数组和切片实例详解

    本文实例讲述了GO语言数组和切片的用法.分享给大家供大家参考.具体分析如下: 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建. 数组有3种创建方式: ...

  2. C语言 数组 列优先 实现

    C语言数组结构列优先顺序存储的实现 (GCC编译). 从行优先转换为列优先存储方式, 与行优先相比, 不同之处在于改变了数组维界基址的先后顺序, 从而改变了映像函数常量基址. /** * @brief ...

  3. C语言 数组 行优先 实现

    C语言数组结构行优先顺序存储的实现 (GCC编译). /** * @brief C语言 数组 行优先 实现 * @author wid * @date 2013-11-02 * * @note 若代码 ...

  4. 不可或缺 Windows Native (5) - C 语言: 数组

    [源码下载] 不可或缺 Windows Native (5) - C 语言: 数组 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 数组 示例cArray.h #ifn ...

  5. C语言数组

    在C语言中,对于三维或三维以上数组的使用并没有很好的支持,而且使用率也非常的低,后面会对三维数组做一些简单的分析,这篇文章主要以二维数组来探讨一些C语言中数组使用的相关概念和技巧. 1 一个var[i ...

  6. C语言数组:C语言数组定义、二维数组、动态数组、字符串数组

    1.C语言数组的概念 在<更加优美的C语言输出>一节中我们举了一个例子,是输出一个 4×4 的整数矩阵,代码如下: #include <stdio.h> #include &l ...

  7. Go语言数组的使用

    Go 语言数组 Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定义类型. 相对于去声明number0 ...

  8. Go 语言数组

    Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定义类型. 相对于去声明number0, number ...

  9. C语言 > 数组和指针

    C语言 数组和指针 const: 关于指针和const需要注意一些规则.首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的. 然而,只能把非const数据的地 ...

  10. Go语言数组和切片的原理

    目录 数组 创建 访问和赋值 切片 结构 初始化 访问 追加 拷贝 总结 数组和切片是 Go 语言中常见的数据结构,很多刚刚使用 Go 的开发者往往会混淆这两个概念,数组作为最常见的集合在编程语言中是 ...

随机推荐

  1. [转帖]linux中的set -e 与set -o pipefail

    https://www.cnblogs.com/xingmuxin/p/8431970.html 1.set -e "Exit immediately if a simple command ...

  2. [转帖]命令行非明文密码连接 TiDB

    https://tidb.net/blog/6794a34b#%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9A%E5%91%BD%E4%BB%A4%E8%A1%8C%E8%BE ...

  3. [转帖]tgz 安装clickhouse

    一.什么是clickhouse ClickHouse是开源的列式存储数据库(DBMS),主要用于在线处理查询(OLAP),能够使用SQL查询实时生成数据分析报告. 下面介绍下安装clickhouse. ...

  4. [转帖]python中input()、print()用法

    https://www.cnblogs.com/lei3082195861/p/16967109.html 1.input()函数常涉及的强制类型转换 第一种是在键入时进行转换,例如:a = int( ...

  5. [转帖]Java 类加载器

      类的生命周期和加载过程 在Java中数据类型分为基本数据类型和引用数据类型.基本数据类型由虚拟机预先定义,引用数据类型则需要进行类的加载.引用类型,Java 将其细分为四种:类.接口.数组类和泛型 ...

  6. 跨主机Docker容器通信的学习

    背景 骨折在家找自己的人比较少. 又因为出不去也没法做运动,就不如将之前没学习深入的地方学习下 先是进行Docker 搭建 redis cluster的处理. 当时发现必须使用 --net=host进 ...

  7. Redis 的简单学习与整理

    Redis 的简单学习与整理 背景 最近一直进行Redis性能调优和高可用的课题 但是不管什么课题,第一步应该是学习与使用redis 之前总结过 rdb 与 rdr 分析 键值对等内容. 但是发现想要 ...

  8. 如何去掉 node.js 获取MySQL数据产生的RowDataPacket

    如何去掉 node.js 获取MySQL数据产生的RowDataPacket 利用JSON.stringify()把对象转为对象字符串,可去掉RowDataPacket. router.post('/ ...

  9. 【小实验】javascript 能够表述的最大整数

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 打开浏览器的控制台,开始输入数值: 输入:(16 位十进制 ...

  10. Natapp 邀请码 积分

    邀请码: 29F145FC 充值95折