走进数组的奇妙之旅

引言:

在前几篇文章中,我们深入探讨了函数的奥秘。在讲述函数知识的过程中,我们邂逅了一个新的概念,你或许还记得在演示 strcpy函数时,出现的这行代码:char1[20]={0};。当时,你是否感到好奇,心中是否升起了疑问:这是什么呢?没错,这正是我们本篇文章的主角——数组

在数字的世界里,数组就像是一座有序排列的宝库,它以一种简洁而高效的方式存储和管理着大量的数据。但你是否真正了解它的奥秘呢?让我们一起踏上探索数组的旅程吧!


1、一维数组

1.1 数组的创建

数组是一组相同类型元素的集合。

你可以这么理解什么是数组:想象一个书架,上面整齐地排列着同一类书籍,这就类似于一个数组。每本书的位置都是固定的,而且它们都属于同一类型(比如都是小说或者都是传记)。

在了解了什么是数组的情况下,我们又产生一个疑问,为什么要引入数组这个概念呢?

我们拿一个例子来解释一下:

存放一串整数,我们用代码可以怎么表示?

#include <stdio.h>
int main()
{int a = 1;int b = 2;int c = 3;//如果我们要存1~100个数字呢?//数组时一组相同类型的元素的集合return 0;
}

如果我们要存1~100的数字,难道我们就这样写下去吗?那也太麻烦了,这时数组就应运而生了!

当我们了解了为什么需要数组后,我们还需要知道该怎么使用它。

数组的创建方式:

type_t  arr_name    [const_n];
// type_t 是指数组的元素类型

// arr_name是指数组的名
// const_n 是一个常量表达式,用来指定数组的大小

比如说:

int arr[10];//整型数组,名为arr [10]指存放了10个元素
double data[20];
char ch[5];//字符数组,名为ch [5]指存放五个字符

也可以同时创建多个相同类型的数组

int arr 1 [10];
int arr 2 [2+8];

这里你或许还会有新的疑问, [ ] 这里面只能用常量或常量表达式吗? 

但是呢,并不是所有情况下都可以使用变量,比如

补充知识点:

在C99标准之前,数组的大小必须是常量或者常量表达式;

在C99之后,数组的大小可以是变量,这是为了支持变长数组;

变长数组的意思是 数组的大小是通过变量来指定的。

上图中的代码想要实现该怎么办呢?

#include <stdio.h>
int main()
{	int n = 10;scanf("%d",&n);int arr[n];	return 0;
}

但是呢,这里还有一个限制条件,就是只能在支持C99标准的编译器上编译

支持C99的编译器:

  • GCC:GNU Compiler Collection 的缩写,它在其编译器集合中提供了 C 编译器,支持 C99 标准。GCC 是一款广泛使用的开源编译器。
  • Clang:基于 LLVM 的 C 编译器,支持 C11 标准,同时也对 C99 有较好的支持。
  • Intel C++ Compiler:英特尔的 C++编译器,也支持 C99 标准。
  • Keil:在 Keil 编译器中,可通过相关设置使其支持 C99(变量声明在执行语句之后)。具体操作是在“Options for Target”中的“C/C++”选项卡下,勾选“C99 Mode”。

1.2 数组的初始化

数组的初始化:在创建数组的同时给数组的内容一些合理初始值(初始化)。

直接代码演示:

int arr1[10] = { 1,2,3 };//不完全初始化,剩余的元素,默认初始化为0
int arr2[] = { 1,2,3,4 };
int arr3[5] = { 1,2,3,4,5 };//完全初始化
char arr4[3] = { 'a',98,'c' };
char arr5[] = { 'a','b','c'};
char arr6[] = { "abcdef" };//[]括号里面也是可以不指定大小的

注意:

1. 不完全初始化(所给元素比指定元素要少),剩余的元素,默认初始化为 0;

2. 括号[ ]里面是可以不指定大小的,这样的话该数组大小(指定值)就等于所给的元素(初始化)。

数组在创建的时候如果不想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。

但是对于下面的代码要会区分,内存中如何分配。

char arr1[10] = { 'a','b','c'};
char arr2[10] = { "abc" };

对于arr1,里面的字符为:a b c 0 0 0 0 0 0 0

对于arr2,里面的字符为:a b c \0 0 0 0 0 0 0

1.3 一维数组的使用

对于数组的使用,我们要介绍了一个操作符: [ ] , 下标引用操作符。它其实就是数组访问的操作符。

int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };	//编号        0 1 2 3 4 5 6 7 8 9//编号是0开始的,这里的编号就是数组的下标       printf("%d\n", arr[4]);return 0;
}

   打印结果是:

 图中可知打印 arr[4]的结果,我们可以得到整数5

使用下标引用操作符arr[i]来访问数组中索引为 i 的元素。

如果我们想把数组的内容全部打印出来,那么范围该怎么确定?

范围不需要我们计算,使用sizeof函数会自动帮我们计算范围。

代码如下:

int main()
{int arr[] = { 1, 2, 3 ,4 ,5 ,6, 7,8 ,9,10 };	//下标范围    0                        9         //printf("%d\n", arr[4]);int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//自动计算范围 左边计算的时总数组的大小  右边的是第一个元素大小for (i = 0; i < sz; i++)//正序打印{printf("%d ", arr[i]);//i是0时打印1,i是1时打印2...}for(i = sz-1;i >= 0;i--)//倒序打印{printf("%d ", arr[i]);}return 0;
}

  下标用来定位数组

注意;使用下标引用操作符时,一定要确保索引值在有效范围内,否则可能导致访问越界错误。

总结:

1.数组是使用下标来访问的,下标是从0开始的。

2.数组的大小可以通过计算得到。                                                    

int sz = sizeof(arr) / sizeof(arr[0]);//计算公式

1.4 一维数组在内存中的存储

数组在内存中是连续存储的,这意味着数组中的元素在内存中是一个紧挨着一个排列的。

 比如说,有一个整数类型的一维数组 int arr[5] = {1, 2, 3, 4, 5} 。

注:地址是16进制的

在 C 语言中,一个整数通常占用 4 个字节的内存空间。

假设这段连续存储空间的起始地址为 0*1000 ,由于在 C 语言中,一个整数通常占用 4 个字节的存储空间。那么,数组中的第一个元素将被存储在地址 0*1000 ,第二个元素紧接着存储在地址 0*1004 ,第三个元素在 0*1008 ,第四个元素在 0*100C ,第五个元素则在 0*1010 。

这种连续存储有两个重要的特点和影响:

一方面,它使得随机访问数组元素的速度非常快。比如说,如果想要获取第三个元素,只需要通过简单的计算 起始地址 + 元素大小 * 索引 (也就是 1000 + 4 * 2 = 1008 ),就能直接找到并访问到第三个元素 3 ,几乎不需要额外的时间去查找。

另一方面,它也带来了一些不便。比如说,如果要在数组中间插入一个新元素,那就需要把插入位置后面的所有元素都向后移动,以腾出空间插入新元素。这是一个比较耗时的操作。同样,删除数组中间的元素时,也需要把后面的元素向前移动来填补空缺。

为了更加直观的解释,我们来用表格辅助理解:

假设有一个整数数组int num[3] = {10,20,30 } ,其在内存中的存储情况如下:

内存地址存储的值
0 * 200010
0 * 200420
0 * 200830

如果现在要在第二个位置插入一个新元素 15 ,那么原有的 20 和 30 都需要向后移动 4 个字节,变成:

内存地址存储的值
0 * 200010
0 * 200415
0 * 200820
0 * 200C30

同样,如果要删除第二个元素 15 ,则 20 和 30 需要向前移动:

内存地址存储的值
0 * 200010
0 * 200420
0 * 200830

综上所述,C 语言中一维数组在内存中的连续存储方式在提供快速随机访问的同时,也在插入和删除操作上带来了一定的复杂性。

当我们知道这一特点后,有助于我们在编程实践中根据具体需求合理地选择和使用数组,或者考虑其他更适合特定操作的数据结构。

所以,理解 C 语言中一维数组在内存中的连续存储方式,对于我们有效地使用数组、优化程序性能以及避免一些常见的错误(比如内存越界访问)都非常重要。

代码展示:

int main()
{int arr[] = { 1, 2, 3 ,4 ,5 ,6, 7,8 ,9,10 };	//下标范围    0                        9         //printf("%d\n", arr[4]);int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//打印数组的每个元素的地址for (i = 0; i < sz; i++){printf("&arr[%d] = %p\n",i, &arr[i]);}return 0;
}

结果展示:

随着数组下标的增加,元素的地址,也在有规律的递增。

2、二维数组

二维数组可以看作是由多个一维数组组成的数组

2.1 二维数组的创建

//数组创建
int arr[3][4];
char arr[3][3];
double arr[1][2];
//3 2 1
//1 2 3
//3 1 2
int main()
{int arr[3][3];return 0;
}

2.2 二维数组的初始化

int main()
{int arr[3][3] = { 3,2,1,1,2,3,3,1,2 };//完全初始化return 0;
}

这样排列元素,会先找前三个放在第一行,再找三个放在第二行,最后三个放在第三行。也就是会按顺序放 

如果所给的元素不够怎么办?

int main()
{int arr[3][3] = { 3,2,1,1,2,3,3};//不完全初始化return 0;
}

 

 我们可以看到少的位置被自动补上了 0 

我们还有另一种方法排放元素

int main()
{int arr[3][3] = { { 3,2},{1,1},{2,3} };//不完全初始化return 0;
}

如果数据不够的时候,我们可以按照分小组的方法,把想要的数据放在适当的位置。

二维数组如果有初始化,行可以省略,列不能省略

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

2.3 二维数组的使用

代码展示: 

#include <stdio.h>
int main()
{int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };int i = 0;for (i = 0;i < 3; i++)//确定行{int j = 0;for (j = 0; j < 4; j++)//确定列{printf("%d", arr[i][j]);}printf("\n");}return 0;
}

 结果展示:

也可以打印其中的单个元素

printf("%d\n",arr[2][0]);
//结果:3

2.4 二维数组在内存中的存储

二维数组可以理解为:一维数组的数组

在 C 语言中,二维数组在内存中是按照行优先(row-major order)的方式连续存储的。

假设我们有一个二维数组 int arr[2][3] ,其在内存中的存储方式类似于将其看作一个一维数组。 先存储第一行的所有元素,然后再存储第二行的元素。

也就是说,内存中元素的排列顺序是 arr[0][0] 、 arr[0][1] 、 arr[0][2] 、 arr[1][0] 、 arr[1][1] 、 arr[1][2] 。

以具体的内存地址为例,如果 arr[0][0] 的地址为 1000 ,且每个 int 类型占用 4 个字节,那么 arr[0][1] 的地址就是 1004 , arr[0][2] 的地址是 1008 , arr[1][0] 的地址是 1012 ,依此类推。

这种连续存储的方式使得可以通过简单的地址计算来快速访问二维数组中的元素。

但需要注意的是,在处理二维数组时,要确保索引不越界,以免访问到非法的内存地址导致程序出错。

2.5 二维数组的实际应用

二维数组在实际编程中有许多应用场景,以下是一些常见的例子:

1. 图像处理:可以用来存储图像的像素信息,其中行和列分别对应图像的高度和宽度。 - 例如,灰度图像可以用二维数组存储每个像素的灰度值。

2. 矩阵运算:如线性代数中的矩阵相加、相乘等操作。 - 在科学计算、机器学习和数值分析中经常用到。

3. 电子表格:类似于 Excel 中的表格数据,可以用二维数组表示行和列的数据。

4. 地图表示:将地图划分为网格,用二维数组存储每个网格的相关信息,如地形、资源等。

5. 游戏开发: - 表示游戏中的棋盘、地图布局。 - 存储游戏中多个角色的位置和状态。

6. 座位安排:例如在会议室、教室等场景中安排座位。

 7. 文本处理:分析文本的二维结构,如表格形式的文本。

这些只是二维数组的一些常见应用场景,实际上,只要数据具有二维的特性并且需要进行批量处理,都可以考虑使用二维数组来进行存储和操作。


结语:

本篇文章即将落下帷幕,在这篇文章中,我们共同探索了一元数组与二元数组的奥秘。在下篇文章中,我们将继续深入挖掘数组知识的精髓,期待您的持续关注与阅读。让我们共同期待,在知识的海洋中,不断探索,不断前行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/873480.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

scp免密复制文件

实现在服务器A和服务器B之间使用scp命令免密互相传输文件 1. 在服务器A中免密复制到服务器B 1.1 生成服务器A的公钥私钥 #在服务器A中执行 ssh-keygen -t rsa -P ""命令执行完毕会在服务器A的 ~/.ssh 目录下生成两个文件&#xff1a;id_rsa 和 id_rsa.pub 1.2 拷…

《Towards Black-Box Membership Inference Attack for Diffusion Models》论文笔记

《Towards Black-Box Membership Inference Attack for Diffusion Models》 Abstract 识别艺术品是否用于训练扩散模型的挑战&#xff0c;重点是人工智能生成的艺术品中的成员推断攻击——copyright protection不需要访问内部模型组件的新型黑盒攻击方法展示了在评估 DALL-E …

外企跨境传输应该如何做到安全有效的文件管控?

跨境文件传输并非易事&#xff0c;它面临着多重挑战&#xff0c;尤其是数据安全、隐私保护以及法律法规遵守等问题。所以如何做到安全有效的文件管控&#xff0c;却是一个让许多企业头疼的问题。小编今天将说说跨境文件传输面临的主要挑战&#xff0c;并讨论如何选择合适的加密…

【深度学习】PyTorch框架(3):优化与初始化

1.引言 在本文中&#xff0c;我们将探讨神经网络的优化与初始化技术。随着神经网络深度的增加&#xff0c;我们会遇到多种挑战。最关键的是确保网络中梯度流动的稳定性&#xff0c;否则可能会遭遇梯度消失或梯度爆炸的问题。因此&#xff0c;我们将深入探讨以下两个核心概念&a…

Linux-mysql数据备份恢复

MySQL数据备份与恢复 一、备份介绍 1、为什么要备份 备份&#xff1a;能够防止由于机械故障以及人为误操作带来的数据丢失&#xff0c;例如将数据库文件保存在了其它地方。 冗余&#xff1a; 数据有多份冗余&#xff0c;但不等备份&#xff0c;只能防止机械故障带来的数据丢…

《JavaSE》---17.<String 类的常见操作>

目录 前言 一、String类的常见用法 1.1 字符串构造&#xff08;常见三种&#xff09; ①使用常量串构造 ②直接newString对象 ③ 使用字符数组进行构造 注意&#xff1a; 1.2 String对象的比较 1. 比较是否引用同一个对象 2. boolean equals(Object anObject) 方法&a…

Activiti7实战

Activiti7与SpringBoot 整合开发 介绍 流程定义如下&#xff1a; 流程如下&#xff1a;申请人提出请假申请后&#xff0c;上级领导看到进行审批&#xff0c;如果时间超过三天&#xff0c;需要校长复审&#xff0c;三天之内直接人事存档。 进入开发工作&#xff0c;具体步骤如…

【数据结构】:时间和空间复杂度在这篇里面一点都不复杂

目录 如何衡量一个代码的好坏 时间复杂度 概念 计算方法 实例计算 【实例1】 【实例2】 【实例3】 【实例4】&#xff1a;冒泡排序的时间复杂度 【实例5】&#xff1a;二分查找的时间复杂度 【实例6】&#xff1a;阶乘递归的时间复杂度 【实例7】&#xff1a;斐波那契…

独立游戏《星尘异变》UE5 C++程序开发日志5——实现物流系统

目录 一、进出口清单 二、路径计算 三、包裹 1.包裹的数据结构 2.包裹在场景中的运动 四、道路 1.道路的数据结构 2.道路的建造 3.道路的销毁 4.某个有道路连接的建筑被删除 作为一个工厂类模拟经营游戏&#xff0c;各个工厂之间的运输必不可少&#xff0c;本游戏采用的…

SQLite数据库在Android中的使用

目录 一&#xff0c;SQLite简介 二&#xff0c;SQLIte在Android中的使用 1&#xff0c;打开或者创建数据库 2&#xff0c;创建表 3&#xff0c;插入数据 4&#xff0c;删除数据 5&#xff0c;修改数据 6&#xff0c;查询数据 三&#xff0c;SQLiteOpenHelper类 四&…

学习008-02-01-05 Configure a One-to-Many Relationship(配置一对多关系)

Configure a One-to-Many Relationship&#xff08;配置一对多关系&#xff09; This lesson explains how to create a One-to-Many relationship between two entities and how XAF generates the UI for such a relationship. 本课介绍如何在两个实体之间创建一对多关系以及…

nginx高可用实例

什么是nginx高可用 为什么需要高可用 正常情况下使用nginx&#xff0c;浏览器访问网址到nginx服务器&#xff0c;nginx再发送到目标服务器&#xff0c;获取资源返回。 但是会有一个问题&#xff1a;当nginx进程发生宕机&#xff0c;此时目标服务器存在&#xff0c;但是浏览器访…

Vue入门之v-for、computed、生命周期和模板引用

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

Linux系统下U-Boot基本操作——UBoot基础知识

个人名片&#xff1a; &#x1f393;作者简介&#xff1a;嵌入式领域优质创作者&#x1f310;个人主页&#xff1a;妄北y &#x1f4de;个人QQ&#xff1a;2061314755 &#x1f48c;个人邮箱&#xff1a;[mailto:2061314755qq.com] &#x1f4f1;个人微信&#xff1a;Vir2025WB…

React基础学习-Day08

React基础学习-Day08 React生命周期&#xff08;旧&#xff09;&#xff08;新&#xff09;&#xff08;函数组件&#xff09; &#xff08;旧&#xff09; 在 React 16 版本之前&#xff0c;React 使用了一套不同的生命周期方法。这些生命周期方法在 React 16 中仍然可以使用…

django报错(二):NotSupportedError:MySQL 8 or later is required (found 5.7.43)

执行python manage.py runserver命令时报版本不支持错误&#xff0c;显示“MySQL 8 or later is required (found 5.7.43)”。如图&#xff1a; 即要MySQL 8或更高版本。但是企业大所数用的还是mysql5.7相关版本。因为5.7之后的8.x版本是付费版本&#xff0c;贸然更新数据库肯定…

RK3562 NPU开发环境搭建

如何在Ubuntu系统&#xff08;PC&#xff09;上搭建RK3562 Buildroot Linux的NPU开发环境&#xff1f;即电脑端运行Ubuntu系统&#xff0c;而RK3562板卡运行Buildroot Linux系统的情况下&#xff0c;搭建RK3562 NPU开发环境。 下面是相应的步骤&#xff08;对应的命令&#xf…

DICOM CT\MR片子免费在线查看工具;python pydicom包加载查看;mayavi 3d查看

DICOM CT\MR片子免费在线查看工具 参考&#xff1a; https://zhuanlan.zhihu.com/p/668804209 dicom格式&#xff1a; DICOM&#xff08;Digital Imaging and Communications in Medicine&#xff09;是医学数字成像和通信的标准。它定义了医学图像&#xff08;如CT、MRI、X…

蓝桥 双周赛算法赛【小白场】

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 蓝桥第14场小白入门赛T1/T2/T3 题目&#xff1a; T1照常还是送分题无需多…

ChatTTS超强的真人AI语音助手下载使用教程

简介 ChatTTS是专门为对话场景设计的文本转语音模型&#xff0c;支持多人同时对话&#xff0c;适用的场景非常丰富&#xff0c;比如LLM助手对话任务&#xff0c;视频配音、声音克隆等。同时支持英文和中文两种语言。最大的模型使用了10万小时以上的中英文数据进行训练&#xf…