重生之我在异世界学编程之C语言:二维数组篇

大家好,这里是小编的博客频道
小编的博客:就爱学编程

很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

本文目录

  • 引言
  • 正文
    • 一 二维数组的创建
      • 1. 二维数组的概念
      • 2. 二维数组的创建
    • 二 二维数组的初始化
      • 1. 不完全初始化
      • 2. 完全初始化
      • 3. 按照行初始化
    • 三 二维数组的使用
      • 1.二维数组的下标
      • 2.使用场景
    • 四 二维数组在内存中的存储
      • 1.存储结构
      • 2.内存布局
      • 3.访问方式
      • 4.地址计算
  • 快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

引言

在C语言中,数组是一种非常重要的数据结构,它允许我们存储固定大小的同类型元素集合。通过使用数组,我们可以方便地处理大量数据,提高程序的效率和可读性。数组的类型分为一位数组和二维数组,还有多维数组,而今天小编将要给大家介绍的是二维数组的相关知识。一起来看看吧!!!

在这里插入图片描述


那接下来就让我们开始遨游在知识的海洋!

正文


首先,我们来看看二维数组的创建

一 二维数组的创建


知其然才能知其所以然,所以我们先来看看二维数组的概念

1. 二维数组的概念

基本概念:C语言的二维数组是一种用于存储具有行和列两个维度的数据集合的结构,类似于数学中的矩阵。在定义时,需要指定数组的行数和列数以及数据类型,例如int array[3][4];表示一个包含3行4列的整型二维数组。每个元素都可以通过其唯一的行索引列索引来访问和操作,非常适合处理表格形式的数据。

相信看过小编上篇关于一维数组的介绍的宝子们对索引一词并不会感到陌生,但这里的行索引列索引又是什么,难道是说明二维数组有两个不同功能的下标?带着这个疑惑,接着往下看。


知道这个二维数组的概念后,我们再来学习二维数组的创建

2. 二维数组的创建

由上易知格式为: 数据类型 数组名[行数][列数]

  • 行索引就是用来访问二维数组的行数,列索引就是用来访问二维数组的列数。具体怎么访问?我们之后再讨论。

以下为例:

int arr[2][3];
double arr1[3][4];

这样我们就创建了两个二维数组。

而事实上,二维数组在创建时是可以省略行数的,但一定不能省略列数。为什么?

其实你仔细思考就可以想到:

省略行数我们可以通过列数推到这个二维数组的行数,但是省略列数我们就得不到二维数组的列数了,没有列数的二维数组又怎么算做一个二维数组?

  • 所以我们在创建一个二维数组时不可省略列数,可以省略行数

所以以下的二维数组的创建正确的

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

2   int  arr [][6] = { 1, 2, 3, 4, 5, 6, 7, 8 };

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

而以下的二维数组的创建错误的

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

2   int  arr [6][] = { 1, 2, 3, 4, 5, 6, 7, 8 };

3   int  arr [7][] = { {1, 2}, {3, 4}, {5, 6} };
  • 好好利用这个知识点,可以在我们不知道我们将会创建多少个元素的二维数组但是知道列数时最大的节约内存空间但也可能造成语法错误。所以一定要牢记:二维数组在创建时是可以省略行数的,**但一定不能省略列数**。

和一维数组一样,学完了二维数组的创建,我们来学二维数组的初始化

二 二维数组的初始化

初始化定义:在创建变量或数组的时候,给定一些初始值,被称为 初始化。二维数组的初始化与一维数组一样,也是用大括号初始化的。


同样地,二维数组的初始化也分为不完全初始化完全初始化,我们先来看看不完全初始化是怎样的。

1. 不完全初始化

顾名思义,不完全初始化就是数组元素并不全部进行赋值的赋值方式

以下为例:

#include<stdio.h>
int main(){
	int arr[2][3] = { 1, 2, 3, 4, 5 };
	return 0;
}

由上可知:

  • 该二维数组的行数列数分别为:【2】和【3】,所以我们不难得出该数组的数组元素的总数为6,而我们可以看到小编这里只对5个元素进行了赋值,是哪5个呢?

我们用监视窗口看一下:

在这里插入图片描述

由图可知:

  • arr[0][0],arr[0][1],arr[0][2],arr[1][0],arr[1][1]被分别初始化为1,2,3,4,5,只有 arr[1][2]没被赋值。所以我们不难看出:二维数组的初始化也是随着下标从小到大进行赋值的,只不过这里的下标行下标列下标,也就是行索引列索引。并且似乎行索引对赋值顺序的决定作用更大。这里就先不深入讨论,后文会细讲。

看完了二维数组的部分初始化,我们再来学习二维数组的完全初始化

2. 完全初始化

说白了,就是对二维数组的全部元素进行了赋值

以下为例:

#include<stdio.h>
int main(){
	int arr[2][3] = { 1, 2, 3, 4, 5, 6};
	return 0;
}

这里同样用监视窗口看一下数组元素有没有被我们放进去初值:

在这里插入图片描述

不出所料,相信这对于聪明的宝子们还是很简单的。那就再接着往下看。


接下来的就是一维数组不具备的独特初始化方式按照行初始化。那一起来看看吧!

3. 按照行初始化

其实,借助这个方法的名字——按照行初始化,我们不难想到这个初始化的方式是不是一行一行地赋初值?

是的,You are so good! ! ! 那该怎么达到我们想要的赋值效果呢?
这就要使用{}这个东东了。

以下为例:

#include<stdio.h>
int main(){
   int arr[2][3] = { {1}, {2, 3}};
   return 0;
}

如果没有使用{},此次的赋值结果由上可知应为arr[0][0] = 1,arr[0][1] = 2,arr[0][2] = 3,arr[1][0] = 0,arr[1][1] = 0,arr[1][2] = 0;

而使用了{}的实际结果如图:
在这里插入图片描述

显然,这里的效果就是我们猜想的结果。

  • 按行初始化可以使得我们给二维数组初始化时更加灵活

在学完了二维数组的创建及初始化后,我们步入了二维数组的使用的学习。

三 二维数组的使用


当然,学习二维数组的使用毫无疑问从二维数组的下标开始学起。

1.二维数组的下标

在C语言中,二维数组可以被看作是一个表格(或矩阵),其中每个元素都有一个行号和列号。这些行号和列号就是所谓的下标,也就是行索引列索引的别称。而二维数组的下标也都是从零开始

假设我们有一个二维数组 arr[m][n],则:

  • m 表示数组的行数。
  • n 表示数组的列数。

那么,数组中的某个元素可以通过 arr[i][j] 来访问,其中:

  • i 是元素的行下标,取值范围是 0 到 m-1
  • j 是元素的列下标,取值范围是 0 到 n-1

例如,对于以下二维数组:

int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};

要访问第二行第三列的元素(即数字7),可以使用 arr[1][2]

2.使用场景

基本使用场景:1. 表示矩阵: 二维数组非常适合用来表示数学上的矩阵。矩阵的运算(如加法、乘法)可以很方便地通过遍历和操作二维数组来实现。2. 图像处理:在图像处理中,图像通常被表示为像素点的集合。一个二维数组可以用来存储图像的灰度值或颜色信息(对于灰度图像,每个元素可以是亮度值;对于彩色图像,可能需要三个二维数组分别存储红、绿、蓝通道的值)。3. 动态规划问题:许多动态规划问题可以用二维数组来记录中间结果。例如,求解最长公共子序列(LCS)、最短路径等问题时,通常会使用一个二维数组来保存已经计算过的状态。4. 网格和地图:在游戏开发和其他应用中,二维数组可以用来表示游戏世界中的网格或地图。每个元素可以代表网格中的一个单元格,包含该单元格的信息(如是否可通行、是否有障碍物等)。5. 其他需要二维数据结构的场景: 除了上述场景外,还有许多其他问题也可以利用二维数组来解决。例如,统计数据的表格、棋盘游戏的状态表示等。

哈哈!宝子们是不是被吓了一跳,小编在刚看到时也被吓了一跳。是不是觉得有很多没听过的专业名词?没关系,小编在之后的日子里会带着大家把这些“拦路虎”一一征服!!!相信小编,也请相信自己!!!

在目前,我们需要掌握的就是二维数组的遍历

如何遍历?这里小编就以最简单的例子按行打印二维数组为例抛砖引玉

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

虽然例子简单,但小编想让大家感受到的是:

  • 一般我们在遍历二维数组时,都会使用两个整型变量ij并初始化为0。至于为什么初始化为0,这也是因为C语言的数组的下标从0开始
  • 且一般会使用两个循环,以for循环最为常见进行遍历

由于现在我们还处于初识二维数组的阶段,所以对二维数组的使用暂讲到这,大家理解完本文可以多去一些刷题网站 加深理解哦!


那现在就让我们进入本文的最后一章节—— 二维数组在内存中的存储

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


这里小编就先从二维数组在内存中的存储结构开始讲起哈。

1.存储结构

从本质上看,二维数组可以被视为“数组的数组”。也就是说,它是一个一维数组的集合,其中每个元素本身又是一个一维数组。例如,int array[3][4]; 表示一个包含3个元素的二维数组,而每个元素都是一个包含4个整数的一维数组。

所以我们引申得到:arr[0]是第一行数组元素的数组名。这很重要,在我们后面理解一维数组和二维数组的数组名有大用。


接着是内存布局

2.内存布局

在内存中,二维数组是连续存储的。具体来说,二维数组的所有元素都按照行优先的顺序排列。这意味着,首先存储第一行的所有元素,紧接着是第二行的所有元素,以此类推,直到最后一行。这种存储方式使得我们可以通过简单的指针运算来访问数组中的任何元素。

这里小编也可以通过打印出一个二维数组的元素的所有地址验证上述说法:

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

运行结果为:

在这里插入图片描述

注:

  • 在64位机器(现在的大部分计算机)中地址的大小是8个字节;
  • '%p’占位符打印的是十六进制表示下的地址;
  • 两个十六进制位数字就占用一个字节

所以我们不难发现:整形数组的相邻数组元素首字节地址大小相差4个字节,也就是一个整型数据的大小。

所以我们可以得出:

  • 二维数组的元素在内存中的存储是连续的,也就是紧挨着的。这和一维数组是一样的

再接着来看看二维数组的访问方式

3.访问方式

由于二维数组在内存中是连续存储的,因此我们可以使用双重循环(嵌套循环)来遍历整个数组。外层循环用于迭代行,内层循环用于迭代列。通过指定行索引和列索引,我们可以轻松地访问或修改数组中的特定元素。

例:

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

运行结果为:
在这里插入图片描述

我们这就通过二维数组的下标(索引)访问并修改了特定的元素的值。


最后我们来看看二维数组的地址计算

4.地址计算

在C语言中,数组名表示的是数组首元素的地址。对于二维数组来说,这个首元素实际上是一个指向其第一行第一个元素的一维数组的指针。因此,如果我们知道数组的首地址以及目标元素的行索引和列索引,就可以计算出该元素的内存地址。这通常涉及到一些基本的算术运算,如乘法(用于跳过前面的行或元素)和加法(用于定位到具体的元素)。

假设这有一个二维数组arr[2][3];,如果我们知道了首元素arr[0][0]的地址,那其他的元素的地址就可以很好的算出。不妨假设&arr[0][0] = 0000000000000000,则&arr[1][2] = 0000000000000018

为什么?这就需要宝子们自己思考啦!!!理解这题就掌握了这节知识——二维数组的内存布局和地址计算

  • 总的来说,C语言的二维数组在内存中是以连续的方式存储的,这使得它们非常适合于需要快速访问和修改大量数据的场景。

快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Tree搜索二叉树、map和set_数据结构

数据结构专栏 如烟花般绚烂却又稍纵即逝的个人主页 本章讲述数据结构中搜索二叉树与HashMap的学习&#xff0c;感谢大家的支持&#xff01;欢迎大家踊跃评论&#xff0c;感谢大佬们的支持! 目录 搜索二叉树的概念二叉树搜索模拟实现搜索二叉树查找搜索二叉树插入搜索二叉树删除…

分离整数的各个数

分离整数的各个数 C语言代码C 语言代码Java语言代码Python语言代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 给定一个整数&#xff0c;要求从个位开始分离出它的每一位数字。 输入 输入一个整数&#xff0c;整数在1到100000000之间…

OpenAI Whisper 语音识别 模型部署及接口封装

环境配置: 一、安装依赖&#xff1a; pip install -U openai-whisper 或者&#xff0c;以下命令会从这个存储库拉取并安装最新的提交&#xff0c;以及其Python依赖项&#xff1a; pip install githttps://github.com/openai/whisper.git 二、安装ffmpeg&#xff1a; cd …

PotPlayer 最新版本支持使用 Whisper 自动识别语音生成字幕

PotPlayer 最新版本支持使用 Whisper 自动识别语音生成字幕 设置使用下载地址 设置 使用 下载地址 https://www.videohelp.com/software/PotPlayer

第33周:运动鞋识别(Tensorflow实战第五周)

目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 1.3 查看数据 二、数据预处理 2.1 加载数据 2.2 可视化数据 2.3 再次检查数据 2.4 配置数据集 2.4.1 基本概念介绍 2.4.2 代码完成 三、构建CNN网络 四、训练模型 4.1 设置动态学习率 4.2 早停与保存最佳模型…

云轴科技ZStack助力 “上科大智慧校园信创云平台”入选上海市2024年优秀信创解决方案

近日&#xff0c;为激发创新活⼒&#xff0c;促进信创⾏业⾼质量发展&#xff0c;由上海市经济信息化委会同上海市委网信办、上海市密码管理局、上海市国资委等主办的“2024年上海市优秀信创解决方案”征集遴选活动圆满落幕。云轴科技ZStack支持的“上科大智慧校园信创云平台”…

Linux 服务器使用指南:诞生与演进以及版本(一)

一、引言 在当今信息技术的浪潮中&#xff0c;Linux 操作系统无疑是一个关键的支柱&#x1f60e;。无论是在服务器管理、软件开发还是大数据处理领域&#xff0c;Linux 都以其卓越的适应性和优势脱颖而出&#x1f44d;。然而&#xff0c;对于许多新手而言&#xff0c;Linux 系统…

基于树莓派3B+的简易智能家居小项目(WiringPi库 + C语言开发)

github主页&#xff1a;https://github.com/snqx-lqh 本项目github地址&#xff1a;https://github.com/snqx-lqh/RaspberryPiSmartHome 硬件开源地址&#xff1a;https://oshwhub.com/from_zero/shu-mei-pai-kuo-zhan-ban 欢迎交流 树莓派智能家居项目&#xff0c;学习树莓派的…

YOLOv8-Pose NCNN安卓部署

YOLOv8-Pose NCNN安卓部署 前言 YOLOv8-Pose NCNN安卓部署 目前的帧率可以稳定在30帧左右&#xff0c;下面是这个项目的github地址&#xff1a;https://github.com/gaoxumustwin/ncnn-android-yolov8-pose 介绍 在做YOLOv8-Pose NCNN安卓部署的时候&#xff0c;在github上…

【热门主题】000077 物联网智能项目:开启智能未来的钥匙

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…

【STM32学习】TB6612FNG驱动芯片的学习,驱动电路的学习

目录 1、TB6612电机驱动芯片 1.1如下是芯片的引脚图&#xff1a; 1.2如下图是电机的控制逻辑&#xff1a; 1.3MOS管运转逻辑 1.3典型应用电路 2、H桥驱动电路 2.1、单极模式 2.2、双极模式 2.3、高低端MOS管导通条件 2.4、H桥电路设计 2.5、自举电路 3、电气特性 3…

day01(Linux底层)基础知识

目录 导学 基础知识 1、Bootloader是什么 2、Bootloader的基本作用 3、入式中常见的Bootloader有哪些 4、Linux系统移植为什么要使用bootloader 5、uboot和Bootloader之间的关系 6.Uboot的获取 7、uboot版本命名 8、uboot版本选择 9、uboot的特点 10.Uboot使用 导学…

OpenFeign 服务调用

1.简介 微服务架构中使用 OpenFeign 进行服务调用&#xff0c; OpenFeign 提供了一种简洁的方式来定义和处理服 务间的调用。 OpenFeign 作为一个声明式的、模块化的 HTTP 客户端&#xff0c;通过 「接口」 的定义和 「注解」 的使用&#xff0c;简化了微服务之间的通信调用。…

superset load_examples加载失败解决方法

如果在执行load_examples命令后,出现上方图片情况,或是相似报错(url error\connection error),大概率原因是python程序请求github数据,无法访问. 因此我们可以将数据下载在本地来解决. 1.下载zip压缩文件,存放到本地 官方示例地址:GitHub - apache-superset/examples-data …

k8s集成skywalking

如果能科学上网的话&#xff0c;安装应该不难&#xff0c;如果有问题可以给我留言 本篇文章我将给大家介绍“分布式链路追踪”的内容&#xff0c;对于目前大部分采用微服务架构的公司来说&#xff0c;分布式链路追踪都是必备的&#xff0c;无论它是传统微服务体系亦或是新一代…

深度学习Python基础(2)

二 数据处理 一般来说PyTorch中深度学习训练的流程是这样的&#xff1a; 1. 创建Dateset 2. Dataset传递给DataLoader 3. DataLoader迭代产生训练数据提供给模型 对应的一般都会有这三部分代码 # 创建Dateset(可以自定义) dataset face_dataset # Dataset部分自定义过的…

【Git教程 之 安装】

Git教程 之 安装 Git教程 之 安装Windows系统安装gitLinux安装gitmacOS安装Git Git教程 之 安装 Windows系统安装git 首先从官网上直接下载安装 选择对应的操作系统&#xff0c;我电脑是Windows&#xff0c;所以我演示以Windows为主 点进去 点击Click here to download 下…

ElasticSearch学习记录

服务器操作系统版本&#xff1a;Ubuntu 24.04 Java版本&#xff1a;21 Spring Boot版本&#xff1a;3.3.5 如果打算用GUI&#xff0c;虚拟机安装Ubuntu 24.04&#xff0c;见 虚拟机安装Ubuntu 24.04及其常用软件(2024.7)_ubuntu24.04-CSDN博客文章浏览阅读6.6k次&#xff0…

【AI】数据,算力,算法和应用(3)

三、算法 算法这个词&#xff0c;我们都不陌生。 从接触计算机&#xff0c;就知道有“算法”这样一个神秘的名词存在。象征着专业、权威、神秘、高难等等。 算法是一组有序的解决问题的规则和指令&#xff0c;用于解决特定问题的一系列步骤。算法可以被看作是解决问题的方法…

Java代码操作Zookeeper(使用 Apache Curator 库)

1. Zookeeper原生客户端库存在的缺点 复杂性高&#xff1a;原生客户端库提供了底层的 API&#xff0c;需要开发者手动处理很多细节&#xff0c;如连接管理、会话管理、异常处理等。这增加了开发的复杂性&#xff0c;容易出错。连接管理繁琐&#xff1a;使用原生客户端库时&…