走进数组的奇妙之旅(1)-学习笔记

引言:

在前几篇文章中,我们深入探讨了函数的奥秘。在讲述函数知识的过程中,我们邂逅了一个新的概念,你或许还记得在演示 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/bicheng/49766.shtml

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

相关文章

【MSP430】MSP430是什么?与STM32对比哪个性能更佳?

一、MSP430是什么&#xff1f; MSP430F5529LP是一款由德州仪器&#xff08;TI&#xff09;推出的16位微控制器单元&#xff08;MCU&#xff09;开发板&#xff0c;具有USB功能&#xff0c;内存配置为128KB闪存和8KB RAM&#xff0c;工作频率高达25MHz。 这款MCU以其高性能和多…

软考中级网络工程师考什么?应该怎么正确备考

网络工程师软考中级难易度50%&#xff0c;不太难。但是如果准备不足就悬了&#xff0c;赶紧备考起来吧。 网络工程师每年考两次&#xff0c;相比其他的软考考试一年中考的机会又多了一次&#xff0c;而且软考网工也是挺热门的科目&#xff0c;每年很多人报考&#xff0c;相对的…

视觉语言动作模型:从网页知识到机器人控制的实战RT-2

作者&#xff1a; Anthony Brohan, Noah Brown, Justice Carbajal, Yevgen Chebotar, Xi Chen, Krzysztof Choromanski, Tianli Ding, Danny Driess, Avinava Dubey, Chelsea Finn, Pete Florence, Chuyuan Fu, Montse Gonzalez Arenas, Keerthana Gopalakrishnan, Kehang Han…

【深度学习】PyTorch框架(5):Transformer和多注意力机制

1、引言 在本文中&#xff0c;我们将探讨近两年来最具影响力的模型架构之一——Transformer模型。自从2017年Vaswani等人发表的论文《注意力是你所需要的全部》以来&#xff0c;Transformer架构在多个领域持续刷新着性能记录&#xff0c;尤其是在自然语言处理&#xff08;NLP&…

DEF_COLOR.py 终端打印显示颜色(Linux/Windows)

打印内容一多&#xff0c;不用颜色区分看着吃力 # -*- coding: utf8 -*- import os## 终端显示颜色 if os.name nt: # Windowsimport ctypes,sysSTD_OUTPUT_HANDLE -11# Windows CMD命令行 字体颜色定义 text colors黑字 0x00 # black.暗蓝字 0x01 # dark blue.暗绿…

C++学习补充2:MySQL select 查询

MySQL select 查询 MySQL 查询 select时&#xff0c; 不区分大小写的。 MySQL 在默认情况下是区分大小写的&#xff0c;但是它的行为可能因配置和使用的字符集而有所不同。以下是一些可能导致查询在 SELECT 语句中不区分大小写的原因&#xff1a; 字符集设置&#xff1a;如果…

释放硬件潜能:Xcode中应用硬件加速开发的深度指南

释放硬件潜能&#xff1a;Xcode中应用硬件加速开发的深度指南 在现代应用开发中&#xff0c;充分利用硬件资源是提升应用性能的关键。Xcode&#xff0c;作为苹果的官方集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了强大的工具和框架来支持硬件加速开发。本文将详…

CSI-RS在信道中传输的过程

简单介绍CSI-RS信号生成&#xff0c;在信道中传输和接收的过程 1.载波配置 首先需要配置载波相关的参数 系统带宽和子载波间隔 5G NR中&#xff0c;系统带宽和子载波间隔是两个关键参数&#xff0c;共同决定无线资源的分配和使用 系统带宽 5G NR支持广泛的系统带宽&…

Xcode应用开发:自定义图表的终极指南

Xcode应用开发&#xff1a;自定义图表的终极指南 在移动应用开发中&#xff0c;图表是一种展示数据的强大工具&#xff0c;它可以帮助用户直观地理解复杂信息。Xcode&#xff0c;作为苹果官方的集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了丰富的工具和框架来创…

碳酸锂溶液树脂吸附除钙镁的方法和工艺流程

碳酸锂溶液作为一种重要的化工原料&#xff0c;主要用于锂电池的制造和其他化学合成过程。它对纯度有较高要求&#xff0c;因此在制备和处理过程中&#xff0c;去除杂质如钙镁离子是非常关键的步骤。 关于碳酸锂溶液除钙镁的方法&#xff0c;几种常见的处理技术包括沉淀法、离…

C++ | Leetcode C++题解之第264题丑数II

题目&#xff1a; 题解&#xff1a; class Solution { public:int nthUglyNumber(int n) {vector<int> dp(n 1);dp[1] 1;int p2 1, p3 1, p5 1;for (int i 2; i < n; i) {int num2 dp[p2] * 2, num3 dp[p3] * 3, num5 dp[p5] * 5;dp[i] min(min(num2, num3…

HTML 基础知识

html文档结构 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><title>页面标题</title> </head> <body><!-- 页面内容 --> </body> </html><!DOCTYPE html>声明文…

解决R语言找不到系统库导致的报错

1、基本需知 1.1、系统库 系统库&#xff08;System library&#xff09;是一组预先编写和编译好的软件模块集合&#xff0c;用于支持操作系统的基本功能和提供一些常见的服务。这些库通常由操作系统或第三方开发者提供&#xff0c;并且在系统安装过程中被预装或者用户可以额…

springboot+vue+mybatis高校宿舍管理系统+PPT+论文+讲解+售后

随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于高校宿舍管理系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了高校宿舍管理系统&#xff0c;它彻底改变了过去传统…

【Linux】从零开始认识多线程 --- 线程互斥

人生有许多事情 正如船后的波纹 总要过后才觉得美的 -- 余光中 线程互斥 1 线程类的封装1.1 框架搭建1.2 线程启动1.3 线程终止1.4 线程等待1.5 运行测试 2 线程互斥2.1 多线程访问的问题2.2 解决办法 --- 锁2.3 从原理角度理解锁 Thanks♪(&#xff65;ω&#xff65;)&am…

Java语言程序设计——篇七(1)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 继承 类的继承实战演练 方法覆盖实战演练 &#x1f351;super关键字实战演练 调用父类的构造方法 类的继承 通过类的继承方式&#xff0c;可以…

手机图片如何转化为word文档?分享3种好用的软件。

在数字化时代&#xff0c;手机已经成为我们生活中不可或缺的一部分。随着手机拍照功能的日益强大&#xff0c;我们常常用手机记录下重要的信息和瞬间。但你有没有遇到过这样的烦恼&#xff1a;如何将手机里的图片快速转化为可编辑的Word文档呢&#xff1f;今天&#xff0c;就为…

基于 G6 的交互式过滤镜:探索图谱数据的新视角

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 G6 的交互式过滤镜&#xff1a;探索图谱数据的新视角 应用场景 交互式过滤镜是一种强大的工具&#xff0c;它允许用户通过聚焦于图谱中的特定区域来探索和分析数据。它在各种场景中都有应用&#xff0c;…

马来西亚外贸服务器租赁公网带宽费用和测速IP地址性能测试

云服务器马来西亚&#xff08;吉隆坡&#xff09;公网带宽租用费用&#xff0c;马来西亚地域按固定带宽计费1M价格22元1个月、按使用流量计费1GB流量费用是0.529元&#xff0c;马来西亚服务器测试IP地址速度如何&#xff1f;阿里云服务器网aliyunfuwuqi.com整理2024年最新马来西…

WebKit引领潮流:CSS环境变量全解析

WebKit引领潮流&#xff1a;CSS环境变量全解析 CSS环境变量&#xff0c;也称为CSS自定义属性或CSS变量&#xff0c;是一种在CSS中使用的特殊类型的变量。它们允许开发者在样式表中定义可复用的值&#xff0c;并在整个文档中重复使用这些值。WebKit作为众多流行浏览器的内核&am…