C语言数组—二维数组


二维数组的创建

//数组创建
int arr[3][4];
//三行四列,存放整型变量
double arr[2][4];

二维数组的初始化

我们如果这样初始化,效果是什么样的呢

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

image-20240318212310793

那如果我们不写满十二个呢

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

image-20240318212428608

不完全初始化,后面默认补0

那我们如何按行初始化呢?
int arr[3][4] = {{1,2},{3,4},{4,5}};

image-20240318212615781

二维数组可以省略行吗
int arr[][4] = {{1,2},{3,4},{4,5}};

image-20240318212742929

所以有几行可以根据初始化的元素来判断,但是有几列无法判断

不可以省略列数,但是可以省略行数

二维数组的使用

这里有一点需要我们注意一下,二维数组的行和列(下标)和一维数组(下标)一样,都是从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;

我们来看运行效果

image-20240318213739143

二维数组在内存中的存储

是怎么样存储的呢?

我们还是和一维数组一样,把二维数组的地址都打印下来

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

看结果

image-20240318214053529

我们注意一下就能发现,每两个数组元素之间的地址都差了4

正好是我们所储存的一个整型变量的空间

所以就说明:

二维数组在内存中也是连续存放的,换行也是连续的

那么我们在回到刚刚的问题,为什么行数可以省略,而列数不能省略呢?

因为地址存放是连续的,有几行直接往后加就行,但是我们如果不知道有几列,就不知道下一行开始时候的地址,所以就无法进行存储

那如果二维数组在内存中是连续的,我们是不是可以通过地址来打印呢?
#include <stdio.h>
int main()
{int arr[][4] = {{1,2},{3,4},{4,5}};int i = 0;int* p = &arr[0][0];for (i = 0; i < 12; i++){printf("%d", *p);p++;}return 0;
}

看结果

image-20240318214928418


其实我们可以这么理解

我现在有一个二维数组

arr[3][4]

那么每一个数组名就是

arr[0] [0]arr[0] [1]arr[0] [2]arr[0] [3]
arr[1] [0]arr[1] [1]arr[1] [2]arr[1] [3]
arr[2] [0]arr[2] [1]arr[2] [2]arr[2] [3]

我们其实也可以把第一行的元素看成数组名为arr[0]的一维数组,下标为[0],[1],[2],[3]

下面几行也是

所以二维数组也可以这么理解

数组越界

数组的下标是有范围限制的。

数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。

所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。

C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就 是正确的,

所以程序员写代码时,最好自己做越界的检查。

#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("%d\n", arr[i]);//当i等于10的时候,越界访问了}return 0;
}

二维数组的行和列也可能存在越界。

数组作为函数参数

往往我们在写代码的时候,会将数组作为参数传个函数,比如:我要实现一个冒泡排序(这里要讲算法 思想)函数将一个整形数组排序。

int main()
{int arr[] = {9,8,7,6,5,4,3,2,1,0};//排序为升序return 0;
}

好的,那么我们开始写一下冒泡排序

bubble_sort(int arr[])
{}
int main()
{int arr[] = {9,8,7,6,5,4,3,2,1,0};bubble_sort(arr);return 0;
}

什么是冒泡排序呢?

思想:

两两相邻的元素进行比较,并且可能的话需要交换

9 8 7 6 5 4 3 2 1 0

8 9 7 6 5 4 3 2 1 0

8 7 9 6 5 4 3 2 1 0

8 7 6 5 4 3 2 1 0 9

一趟冒泡排序后,有一个数字一定来到他最终应该在的位置上

一趟解决一个数组

8 7 6 5 4 3 2 1 0 9

7 8 6 5 4 3 2 1 0 9

7 6 8 5 4 3 2 1 0 9

7 6 5 4 3 2 1 0 8 9

十个数字就需要就趟排序,n个数字就需要n-1趟排序


所以我们来写函数

bubble_sort(int arr[])
{//计算数组元素个数int sz = sizeof(arr)/sizeof(arr[0]);//确定趟数int i = 0;for(i = 0, i< sz - 1, i++)//这里的sz - 1就是循环的趟数{//一趟冒泡排序的过程int j = 0;for(j=0; j<sz-i-1; j++)//这里的sz-i-1就是每一次比较的个数,每次循环都会把一个数字放在正确的位置,那么我们只需要比较前面的数字就行{if(arr[j] > arr[j+1]){int tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = tmp;}
}//这就是冒泡排序

我们来看运行

image-20240318223112452

好的我们看到,在这里已经出现问题了,我们在传参的时候并没有传递完整数组

问题出在哪呢?
bubble_sort(int arr[])//arr的本质是指针int sz = sizeof(arr)/sizeof(arr[0]);//那sizeof(arr)应该是4个字节bubble_sort(arr);//数组在传参的时候,传递的其实是数组首元素的地址

所以,我们应该在函数外面计算数组的长度,作为参数传递进函数

#include <stdio.h>
bubble_sort(int arr[],int sz)
{//确定趟数int i = 0;for (i = 0; i < sz - 1; i++)//这里的sz - 1就是循环的趟数{//一趟冒泡排序的过程int j = 0;for (j = 0; j < sz - i - 1; j++)//这里的sz-i-1就是每一次比较的个数,每次循环都会把一个数字放在正确的位置,那么我们只需要比较前面的数字就行{if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}//这就是冒泡排序}
}int main()
{int arr[] = { 9,8,7,6,5,4,3,2,1,0 };//计算数组元素个数int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr,sz);return 0;
}

image-20240318223639076

image-20240318223656100

成功!

还有几个问题值得探讨一下

数组名是什么?

数组名是数组首元素的地址

但是有两个例外

  1. sizeof(数组名) 数组名表示数组 计算的是整个数组的大小
  2. &数组名 数组名表示的是整个数组 取出的是整个数组的地址
int main()
{int arr[10] = { 0 };int sz = sizeof(arr);printf("%p\n", &arr);printf("%p\n", arr);printf("%p\n", &arr[0]);printf("%d\n", sz);return 0;
}

image-20240318224217865

最后一个很好理解,为什么前三个地址都相同呢?

首先,数组名就是首元素地址,所以第二行和第三行相同是没错的

但是第一行,&arr取出的实际上是数组的地址

只是数组的地址和数组首元素的地址是相同的

怎么去理解呢?
int main()
{int arr[10] = { 0 };int sz = sizeof(arr);printf("%p\n", &arr);printf("%p\n", &arr + 1);printf("%p\n", arr);printf("%p\n", arr + 1);return 0;
}

image-20240318224630022

我们很明显能看出来,数组地址的下一个地址和上一个差了A8-D0,转换成10进制就是40个字节

而数组首元素的下一个地址和本身只是差了4个字节

所以说虽然他们看起来一样,但是实际上表达的含义是不一样的

所以当数组以形参传到函数内部时,是无法计算元素个数的

希望大家多多注意

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

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

相关文章

一文快速掌握docker的理念和基本使用

写在文章开头 写于一个周末&#xff0c;在复盘梳理文章时候发现这一篇关于早期了解docker时记录的文档&#xff0c;仔细阅读了一下&#xff0c;为了保证文章更加清晰以便读者使用。故再次重新一次梳理一次&#xff0c;通过这篇文章&#xff0c;你将会对docker的基本理念和基础…

Stable Diffusion WebUI 生成参数:采样器(Sampling method)和采样步数(Sampling steps)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 本文将深入探讨Stable Diffusion WebUI生成参数中的采样器和采样步数&#xff0c;旨在为读者呈现一个全面而细致的解析。我们将从采样器和采样步数的概念出发&…

内网安全之-NTLM协议详解

NTLM&#xff08;New Technology LAN Manager&#xff09;身份验证协议是微软用于Windows身份验证的主要协议之一。早起SMB协议以明文口令的形式在网络上传输&#xff0c;因此产生了安全性问题。后来出现了LM&#xff08;LAN Manager&#xff09;身份验证协议&#xff0c;它非常…

数据可视化实战(二)

将每个城市在每个月份平均PM2.5绘制成折线图 import pandas as pd import matplotlib.pyplot as plt df pd.read_excel(./PM2.5.xlsx)display(df.head(10)) df.shape # (161630, 15)城市年份月份日期小时季节PM2.5露点湿度压强温度风向累计风速降水量累计降水量0北京2010112…

qt+ffmpeg 实现音视频播放(二)之音频播放

一、音频播放流程 1、打开音频文件 通过 avformat_open_input() 打开媒体文件并分配和初始化 AVFormatContext 结构体。 函数原型如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options); 参数说…

Docker的简介及安装

Docker 是什么 Docker是在Linux容器里运行应用的开源工具&#xff0c;是一种轻量级的“虚拟机”。诞生于2013年&#xff0c;最 初的发起者是dotCloud公司&#xff0c;后来改名为Docker Inc&#xff0c;专注于Docker 相关技术和产品的开发。Docker 项目目前已经加入了Linux基金会…

【办公类-22-11】周计划系列(5-3)“周计划-03 周计划内容循环修改“ (2024年调整版本)

背景需求&#xff1a; 前文从原来的“新模版”文件夹里提取了周计划主要内容和教案内容。 【办公类-22-10】周计划系列&#xff08;5-2&#xff09;“周计划-02源文件docx读取5天“ &#xff08;2024年调整版本&#xff09;-CSDN博客文章浏览阅读1.1k次&#xff0c;点赞29次&…

基于消失点的相机自标定

基于消失点的相机自标定 附赠最强自动驾驶学习资料&#xff1a;直达链接 相机是通过透视投影变换来将3D场景转换为2D图像。在射影变换中&#xff0c;平行线相交于一点称之为消失点。本文详细介绍了两种利用消失点特性的标定方法。目的是为根据实际应用和初始条件选择合适的标…

边缘计算+WEB端应用融合:AI行为识别智能监控系统搭建指南 -- 云端系统数据库设计(五)

专栏目录 边缘计算WEB端应用融合&#xff1a;AI行为识别智能监控系统搭建指南 – 整体介绍&#xff08;一&#xff09; 边缘计算WEB端应用融合&#xff1a;AI行为识别智能监控系统搭建指南 – 边缘设备图像识别及部署&#xff08;二&#xff09; 边缘计算WEB端应用融合&#xf…

【开发】Redis 的理解与数据存储格式

目录 相关传送门 1. NOSQL和关系型数据库比较 2. 主流的NOSQL产品 3. Redis的理解 4. redis数据存储格式 4.1 String 4.2 Hash 4.3 List 4.4 Set 4.5. sorted_set 注&#xff1a;手机端浏览本文章可能会出现 “目录”无法有效展示的情况&#xff0c;请谅解&#xf…

Hive:数据仓库利器

1. 简介 Hive是一个基于Hadoop的开源数据仓库工具&#xff0c;可以用来存储、查询和分析大规模数据。Hive使用SQL-like的HiveQL语言来查询数据&#xff0c;并将其结果存储在Hadoop的文件系统中。 2. 基本概念 介绍 Hive 的核心概念&#xff0c;例如表、分区、桶、HQL 等。 …

Tomcat Session ID---会话保持

简单拓补图 一、负载均衡、反向代理 7-1nginx代理服务器配置 [rootdlnginx ~]#yum install epel-release.noarch -y ###安装额外源[rootdlnginx ~]#yum install nginx -y[rootdlnginx ~]#systemctl start nginx.service[rootdlnginx ~]#systemctl status nginx.service [ro…

Javaweb学习记录(四)分层处理架构-分层解耦

三层架构 程序设计分为下面三层架构&#xff0c;分别为Controller控制层&#xff0c;Service逻辑处理层&#xff0c;Dao数据访问层。这三层各自执行自己所对应的功能&#xff0c;使程序的扩展性和可维护性提高 例如下面我想设计一个分层的程序&#xff0c;实现Controller层&am…

MidJourney 使用指北

官网&#xff1a;docs.midjourney.com 文档&#xff1a;docs.midjourney.com/docs/quick-… PS&#xff1a;魔法需要订阅使用了 准备工作 一、进入 discord官网 二、下载 Discord App 三、注册Discord账号 创建服务器 登录 discord App&#xff0c;点击添加按钮&#xff…

AJAX——综合案例

1 Bootstrap弹框 功能&#xff1a;不离开当前页面&#xff0c;显示单独内容&#xff0c;供用户操作 步骤&#xff1a; 引入bootstrap.css和bootstrap.js准备弹框标签&#xff0c;确认结构通过自定义属性&#xff0c;控制弹框的显示和隐藏 <!DOCTYPE html> <html la…

详解Java常用排序算法(10种,含演示动画)

Java常用的排序算法有以下几种&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;选择排序&#xff08;Selection Sort&#xff09;插入排序&#xff08;Insertion Sort&#xff09;希尔排序&#xff08;Shell Sort&#xff09;归并排序&#xff08;Merge Sort&#x…

Android Studio:你的主机中的软件终止了一个已建立的连接

我不喜欢等人也不喜欢被别人等——赤砂之蝎 一、提出问题 二、分析问题 搜索网上的教程尝试解决 1、任务管理器结束adb进程无用 2、电脑没有开启热点排除热点问题 3、校园网切换到热点 4、项目重新解压打开 5、更换国内镜像源 上述方法全部无法解决问题 分析问题原因在于之前A…

Github 2024-03-18 开源项目周报Top15

根据Github Trendings的统计,本周(2024-03-18统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6TypeScript项目2Go项目2JavaScript项目2非开发语言项目1HTML项目1CSS项目1Rust项目1Dart项目1C++项目1Jupyter Notebook项目1Electr…

JVM中对象创建过程

在JVM中对象的创建&#xff0c;我们从一个new指令开始&#xff1a; 这个过程大概图示如下&#xff1a; 虚拟机收到new指令触发。 类加载检查&#xff1a;如果类没有被类加载器加载&#xff0c;则执行类加载流程&#xff08;将class信息加载到JVM的运行时数据区的过程&#xff…

Stable Diffusion + Segment Anything试用

安装 从continue-revolution/sd-webui-segment-anything安装插件分割模型下载后放到这个位置&#xff1a;${sd-webui}/extension/sd-webui-segment-anything/models/sam下&#xff0c;可以下载3个不同大小的模型&#xff0c;从大到小如下&#xff1a;vit_h is 2.56GB, vit_l i…