欢迎大家来到贝蒂大讲堂

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

所属专栏: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. [转帖]FIO 存储性能压测

    一. FIO简介 FIO 是一个多线程IO生成工具,可以生成多种IO模式(随机.顺序.读.写四大类),用来测试磁盘设备的性能.GFIO是FIO的图形监测工具,它提供了图形界面的参数配置,和性能监测图像 ...

  2. [转帖]如何升级vCenter(VCSA)补丁?

    https://www.dinghui.org/upgrade-vcsa-patch.html VCSA的升级分为repo源和iso镜像两种方式,由于使用repo源进行升级只支持HTTPS和FTPS协 ...

  3. [转帖]Kdump配置及使用(详细)总结(二)

    一.简介 本文主要介绍如何打开Kdump并对其相关文件进行配置.前面章节已经对Kdump调试机理进行总结总结,具体可以点击下面链接: Kdump调试机理总结(一) crash工具分析vmcore文件常 ...

  4. SPECJVM2008 再学习

    SPECJVM2008 再学习 摘要 昨天的太水了 感觉今天有必要再水一点.. 存在的问题 默认进行启动 sunflow 必定过不去. 一般的解决办法要求进行重新编译 但是我不知道怎么下载源码... ...

  5. 一次典型的Memroy Leak的跟踪学习过程

    背景 周四时某项目在QQ群里说自己的系统出现了CPU占用较高的情况. TOP 查看发现大部分占用CPU的都是 JAVA核心进城后附近的进程. 所以初步怀疑 是出现了FullGC的问题. 然后群里反馈了 ...

  6. vue中sync的使用原来这么简单

    sync的使用场景 有些时候子组件需要修改父组件传递过来的prop, 要去改变父组件的状态的时候就需要使用aync 看见这里有些同学可能会问?? 不是说不可以修改父组件传递到子组件的值吗? 为啥要修改 ...

  7. 爬虫逆向基础,认识 SM1-SM9、ZUC 国密算法

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! [01x00] 简介 国密即国家密码局认定的国产加密算法,爬虫工程师在做 JS 逆向的时候,会遇 ...

  8. 【scikit-learn基础】--『回归模型评估』之准确率分析

    分类模型的评估和回归模型的评估侧重点不一样,回归模型一般针对连续型的数据,而分类模型一般针对的是离散的数据. 所以,评估分类模型时,评估指标与回归模型也很不一样,比如,分类模型的评估指标通常包括准确率 ...

  9. lua开发和调试环境

    Lua开发环境搭建 Lua官网提供源码下载需要自己编译,Lua官网:https://www.lua.org/ftp/ lua for windows.exe(占二十多MB那个) 目前在网络上没有找到 ...

  10. TienChin-课程管理-展示课程列表

    配置按钮权限 博主这里就不贴SQL了,自行手动添加一下吧. 更改表结构 ALTER TABLE `tienchin_course` MODIFY COLUMN `info` varchar(255) ...