[C++] 数组 详解

[C++] 数组 详解

前言

大家好啊,zty来更C++的基础之一,那就是数组,作为一个我们做题或者是开发一些内容都不可或缺的一个知识,那我们今天就来深入的去了解一下他,给他来个详解好吧,上一周的多态详解没有到100赞啊,这个博客我想要个100赞可不可以,zty呢最近在冲榜,大家多多支持一下啊,我的目标就是在寒假结束以前冲进前3000好吧,马上正月十五了,祝大家阖家团圆好吧

                                                  先   赞   后   看    养   成   习   惯 

众所周知,一篇文章需要一个头图,但我家盛产头图

                                                  先   赞   后   看    养   成   习   惯  

上面那行字怎么读呢,让大家来跟我一起读一遍吧,先~赞~后~看~养~成~习~惯~

演示用编译器及其标准

Dev C++ 6.7.5 Red panda 

想下载编译器的宝宝们点我好吧

标准是 C++14(其实C++11也可以的)

目录

前言

演示用编译器及其标准

作者有话说

    先   赞   后   看    养   成   习   惯  

正文

概述

一维数组

定义方式

一维数组定义的3种方式:

1,数据类型 数组名[ 数组长度 ];

 2,数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};

3,数据类型 数组名[ ] = { 值1,值2 ...}; 

一维数组名 

 一维数组名称的作用

一维数组名的2种特例情况

一维数组的地址 

一维数组的排序

sort

二维数组

二维数组定义方式

二维数组数组名 

 二维数组的地址

 好啊今天的数组呢就讲到这里,为什么讲的这么短呢因为我懒,因为这个数组本身就比较好理解

后记


作者有话说

最近,作者也是高光了一回啊,写的那片篇结构体博客,被洛谷站长给推荐了(kkksc03),这哥们可是个大人物啊,接下来上图片好吧

                                               

                                                                           先   赞   后   看    养   成   习   惯  

正文

终于到正文了,不瞎掰掰直接开始

概述

数组是一个集合,用于存放相同类型的数据元素。

特点1:数组中的每个数据元素具有相同的数据类型。
特点2:数组占用一段连续的内存空间。

 举个例子,就像城市中的那种高层楼房,占用了一块连续的空间,而且那个楼里边呢每一个屋子基本都是一个类型的,这个就是数组,当然我举的这个例子是一位数组,二维数组呢就像一个棋盘,每一个格子中放的类型都是一样的,还有三维四维五维等等,但是我们都不常用,我也就不去挨个的举例子了

一维数组

定义方式

注1:数组名的命名规范与变量名命名一致,且数组名不能与变量重名。
注2:数组的下标/索引从0开始。

一维数组定义的3种方式:
1,数据类型 数组名[ 数组长度 ];

就像这样

int zty[114514];
注:定义数组时,若未给定数组元素的初始值,则必须指定初始数组长度,否则提示错误:“不允许使用不完整的类型”。
 2,数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};

就像这样

int zty[6]={1,1,4,5,1,4};

注:数组初始化时,若大括号{ }内的元素个数小于定义的数组长度,则剩余数组元素默认使用 0 填充。 

3,数据类型 数组名[ ] = { 值1,值2 ...}; 

就是这样

int zty[]={1,1,4,5,1,4};
注:定义数组元素初始值时,数组可以不指定初始数组长度。

来个示例要不然不清楚 

int main() { //定义方式1:数据类型 数组名[元素个数]; int arr[10]; //使用数组下标对数组元素进行赋值或访问 arr[0] = 10; arr[1] = 20; arr[2] = 30; //定义方式2:数据类型 数组名[元素个数] = {值1,值2 ,值3 ...}; //若大括号{ }内的元素个数小于定义的数组长度,则剩余数据默认使用0填充 int arr2[10] = { 100,90,80,70,60,50,40,30,20,10 }; //定义方式3: //数据类型 数组名[] = {值1,值2 ,值3 ...}; int arr3[] = { 100,90,80,70,60,50,40,30,20,10 }; return 0; } 
一维数组名 
 一维数组名称的作用

(1)统计整个数组的长度,例:sizeof(arr) / sizeof(arr[0]);

数组占用内存空间大小:sizeof(arr)
数组单个元素占用内存空间大小:sizeof(arr[0])
数组长度sizeof(arr) / sizeof(arr[0])

(2)获取数组在内存中的首地址,例:arr。

获取数组首地址:arr&arr[0]
 注:arr&arr[0]:数组首元素的地址 ;
&arr:整个数组的地址【地址值相同,含义不同】。

一维数组名的2种特例情况

一维数组名不表示数组首元素地址的两种特例:

sizeof(数组名):整个数组的大小;
&数组名:整个数组的地址(地址值与首元素地址相同,但意义不同),表示数组指针。

注:其它情况下,一维数组的数组名均表示数组首元素地址,等价于相应的指针类型。

示例

int main() { //数组名用途 //1、获取整个数组占用内存空间大小 int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; cout << "整个数组所占内存空间为: " << sizeof(arr) << endl; cout << "每个元素所占内存空间为: " << sizeof(arr[0]) << endl; cout << "数组的元素个数为: " << sizeof(arr) / sizeof(arr[0]) << endl; //2、获取到数组首地址 cout << "数组首地址为: " << (int)arr << endl; cout << "数组中第一个元素地址为: " << (int)&arr[0] << endl; cout << "数组中第二个元素地址为: " << (int)&arr[1] << endl; //arr = 10; //错误:数组名是常量,不可赋值 return 0; } 
 注1:数组名是常量,不能进行赋值,否则报错:表达式必须是可修改的左值
注2:对数组名使用sizeof,可获取整个数组占内存空间的大小。
一维数组的地址 

【以整型一维数组int arr[n]为例】

(1) arr等价于&arr[0]

  1. 表示数组首元素地址,指向数组第1个元素,arr + 1&arr[0] + 1会跳过第1个元素【加上1个数组元素的字节数】,指向数组的下1个元素。
  2. arr&arr[0]的地址类型为int *类型,使用int类型的指针(指向数组首元素的指针)接收。

(2) &arr

  1. 表示整个数组的地址,指向整个数组,&arr + 1会跳过整个数组【加上整个数组的总字节数】,如int *p = (int *)(&arr + 1),指针p指向数组的末尾。
  2. &arr的地址类型为int (*)[数组长度]类型,使用数组指针(指向数组的指针)接收。
#include<bits/stdc++.h> using namespace std; int main() { //一维数组 int arr[5] = { 1, 2, 3, 4, 5 }; /* 一维数组的地址与指针 */ int* p1 = (int *)(&arr + 1); //&arr:整个数组的地址 //&arr + 1:指向数组的末尾处 int* p2 = (int*)(arr + 1); //arr等价于&arr[0],类型为int *类型:数组首元素地址 cout << p1[-2] << endl; cout << *p2 << endl; cout << arr << endl; cout << *arr << endl; cout << arr + 1 << endl; cout << *(arr + 1) << endl; cout << &arr[0] << endl; cout << *(&arr[0]) << endl; cout << &arr[0] + 1 << endl; cout << *(&arr[0] + 1) << endl; cout << &arr << endl; cout << *(&arr) << endl; cout << &arr + 1 << endl; // 后移4*5=20字节【跳过整个数组】 cout << *(&arr + 1) << endl; // return 0; }

一维数组的排序

通常的一维数组主要是用 sort 进行排序。

sort

 sort使用起来这非常的简单,只需要一行代码

sort(数组名,数组名+数组需要排序的长度,排序方法);

这三个参数我们一个个来讲

第一个参数是数组名,这个好理解这个应该就不需要讲了吧,就是你需要排序的数组名

第二个参数呢,只需要排序的长度,这个地方可以填树也数也可以填变量

第三个参数呢是排序方法,这个是可以不填的,不填的话默认就是从大到小排序,如果是填的话需要单独写一个函数,这个函数呢要有两个参数而且不能是void类型,返回值是排序方法

给大家来个示例啊

#include<bits/stdc++.h> using namespace std; int cmp(int a, int b) {//这个是从小到大排序 return a > b; } int main() { int zty1[6] = {1, 1, 4, 5, 1, 4}; int zty2[6] = {1, 1, 4, 5, 1, 4}; // 不填第3个参数的情况下 sort(zty1, zty1 + 6); for (int i = 0; i < 6; i++) { cout << zty1[i] << " "; } cout<<endl; // 填第3个参数的情况下 sort(zty2, zty2 + 6, cmp); for (int i = 0; i < 6; i++) { cout << zty2[i] << " "; } return 0; }

一维数组呢我们就讲完了,接下来我们讲二维数组

二维数组

二维数组的每个元素均为一个一维数组,可用矩阵的形式表示。

二维数组定义方式

二维数组定义的4种方式:

(1)数据类型 数组名[ 行数 ][ 列数 ];
(2)数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2} ,{数据3,数据4} };
(3)数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};
(4)数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4};

注1:第(2)种定义方式更直观,可提高代码的可读性;第(3)、(4)种根据二维数组的列数推断数组元素(可省略行数,不可省略列数)。
注2:定义二维数组时,若已初始化数据,则可以省略行数
int main() { int arr[2][3] = { {1,2,3},{4,5,6} }; for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { for (int j = 0; j < sizeof(arr[i]) / sizeof(arr[i][0]); j++) { cout << arr[i][j] << " "; } cout << endl; } return 0; } 
二维数组数组名 

二维数组名称的作用

(1)计算二维数组所占内存空间

二维数组占用内存空间大小:sizeof(arr)
二维数组第 i 行占用内存空间大小:sizeof(arr[i])
二维数组某个元素占用内存空间大小:sizeof(arr[i][j])

(2)计算二维数组的行数列数

二维数组的行数:sizeof(arr) / sizeof(arr[0])
二维数组的列数:sizeof(arr[0]) / sizeof(arr[0][0])

(3)获取二维数组的首地址

二维数组首地址:arr[0]&arr[0][0]
二维数组第1个元素的地址: arr[0]&arr[0][0]

二维数组第 0 行的地址arrarr[0]arr + 0 【或*(arr + 0)
二维数组第 i 行的地址:arr[i]arr + i 【或*(arr + i)&a[0] + i
注:arr[0]&arr[0][0]:二维数组首元素的地址 ;
二维数组名arr:二维数组第0行(首行)的地址,等价于arr[0]arr + 0 

(4)二维数组的其它地址

二维数组第 i 行首元素的地址arr[i]arr + i*(arr + i)&a[0] + i
二维数组第 i 行第 j 列元素的地址&arr[i][j]*(arr + i) + j

(5)通过指针解引用访问或操作某元素:*(*(arr + i) + j)

int main() { int arr[2][3] = { {1,2,3},{4,5,6} }; //二维数组占用的内存空间 cout << "二维数组大小: " << sizeof(arr) << endl; //24 cout << "二维数组一行大小: " << sizeof(arr[0]) << endl; //12 cout << "二维数组元素大小: " << sizeof(arr[0][0]) << endl; //3 //二维数组的行数与列数 cout << "二维数组行数: " << sizeof(arr) / sizeof(arr[0]) << endl; //2 cout << "二维数组列数: " << sizeof(arr[0]) / sizeof(arr[0][0]) << endl; //3 //地址 cout << "二维数组首行地址:" << (int)arr << endl; //16053988 cout << "二维数组第一行地址:" << (int)arr[0] << endl; //16053988 cout << "二维数组第一个元素地址:" << (int)&arr[0][0] << endl; //16053988 cout << "二维数组第二行地址:" << (int)arr[1] << endl; //16054000 cout << "二维数组第二个元素地址:" << (int)&arr[0][1] << endl; //16053992 system("pause"); return 0; } 
 二维数组的地址

【以整型二维数组int arr[m][n]为例】

(1) arr[0]等价于&arr[0][0]

1,表示二维数组首元素地址,指向二维数组第0行第0列元素, arr[0] + 1等价于&arr[0][0] + 1会在二维数组第0行跳过第1个元素【加上1个数组元素的字节数】,指向二维数组第0行的下1个元素。

2,arr[0]&arr[0][0]的地址类型为int *类型,使用int类型的指针(指向数组第0行首元素的指针)接收。如int *p = arr[0];int *p = &arr[0][0];

(3) &arr

1,表示整个二维数组的地址,指向整个二维数组,&arr + 1会跳过整个二维数组【加上整个二维数组(共m * n个元素)的总字节数】,指向数组的末尾。

2,&arr的地址类型为int (*)[数组行数][数组列数]类型,使用二维数组指针(指向数组的指针)接收。如int (*p)[3][4] = &arr;

示例

#include <iostream> using namespace std; int main() { //二维数组3行4列 int arr[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} }; cout << &arr << endl; //00DAFB34 //整个二维数组的地址 cout << &arr + 1 << endl; //00DAFB64 /后移4*3*4=48字节【跳过整个二维数组的全部12个元素】 cout << arr << endl; //00DAFB34 //二维数组第0行的地址 cout << arr + 1 << endl; //00DAFB44 后移4*4=16字节【跳过二维数组1行共4个元素】 cout << arr[1] << endl; //00DAFB44 后移4*4=16字节【跳过二维数组1行共4个元素】 cout << &arr[0] + 1 << endl; //00DAFB44 后移4*4=16字节【跳过二维数组1行共4个元素】 cout << *(arr + 1) << endl; //00DAFB44 //二维数组第1行首元素的地址 cout << *(arr + 1) + 1 << endl; //00DAFB48 后移4字节【跳过1个元素】 cout << arr[0] << endl; //00DAFB34 //二维数组首元素地址 cout << arr[0] + 1 << endl; //00DAFB38 后移4字节【跳过1个元素】 cout << &arr[0][0] << endl; //00DAFB34 //二维数组首元素地址 cout << &arr[0][0] + 1 << endl; //00DAFB38 后移4字节【跳过1个元素】 /* 数组指针,指向数组长度为4的int数组 */ //arr或&arr[0]:地址类型int(*)[4] int (*p1)[4] = arr; //正确 int (*p2)[4] = &arr[0]; //正确 //&arr:地址类型int(*)[3][4] int(*p)[3][4] = &arr; //正确 return 0; } 

 好啊今天的数组呢就讲到这里,为什么讲的这么短呢因为我懒,因为这个数组本身就比较好理解

后记

作者:zty郑桐羽呀

联系方式:(不挂了,有事看主页QQ号加QQ)

兄弟们给个赞呗

                                                  先   赞   后   看    养   成   习   惯  

Read more

从云原生部署到智能时序分析:基于 Kubernetes 的 Apache IoTDB 集群实战与 TimechoDB 国产化增强特性深度解析

从云原生部署到智能时序分析:基于 Kubernetes 的 Apache IoTDB 集群实战与 TimechoDB 国产化增强特性深度解析

从云原生部署到智能时序分析:基于 Kubernetes 的 Apache IoTDB 集群实战与 TimechoDB 国产化增强特性深度解析 前言 随着物联网设备规模的指数级增长,传感器产生的海量时序数据对传统数据库的性能、可扩展性与成本控制提出了更高要求。Apache IoTDB 作为专为物联网场景设计的时序数据库,凭借高压缩比、百万级写入能力及毫秒级查询性能,成为物联网数据存储与分析的核心基础。本文将从 IoTDB 的核心特性 出发,深入讲解其在 Kubernetes 环境中的部署实践、CRUD 操作示例,并延伸至 TimechoDB 的国产化增强能力,帮助读者全面掌握从单节点到云原生集群的 IoTDB 实战部署与应用方法,为构建高效、可扩展的时序数据平台提供系统参考。 Apache IoTDB 核心特性与价值 Apache IoTDB 专为物联网场景打造的高性能轻量级时序数据库,以 “设备 - 测点” 原生数据模型贴合物理设备与传感器关系,通过高压缩算法、百万级并发写入能力和毫秒级查询响应优化海量时序数据存储成本与处理效率,同时支持边缘轻量部署、

By Ne0inhk

Docker 零基础入门:一篇搞懂 Docker 是什么、为什么要用它

适合人群:纯新手、没接触过容器、只想先搞懂 Docker 核心概念的同学文章定位:不讲底层原理、不写复杂命令,只说清楚「Docker 是干啥的」「为什么项目离不开它」 一、前言:先说说你一定会遇到的痛点 做开发 / 运维的朋友,大概率都听过这句话:「在我电脑上跑的好好的,怎么到服务器上就报错了?」 * 开发用 Windows,测试用 Mac,生产用 Linux,环境不一样 * 项目依赖的 JDK、Python、MySQL、Nginx 版本不统一 * 装一个软件要配一堆环境,换台机器就得重来一遍 * 多个项目依赖冲突,改一个崩另一个 这些问题,Docker 就是专门来解决的。 二、Docker 到底是什么?(大白话版) 1. 最通俗的比喻:Docker = 「软件集装箱」 你可以把服务器看成一艘大货轮,应用

By Ne0inhk
【Linux指南】进程控制系列(五)实战 —— 微型 Shell 命令行解释器实现

【Linux指南】进程控制系列(五)实战 —— 微型 Shell 命令行解释器实现

前面四篇文章,我们已经掌握了进程控制的 “全链路技能”:用fork创建子进程、exec替换程序、waitpid回收资源、exit终止进程。今天,我们将这些知识 “组装” 成一个能实际运行的工具 ——微型 Shell 命令行解释器(简称 “迷你 Shell”)。 这个迷你 Shell 将支持:命令行提示符(如[user@host dir]#)、内建命令(cd/export/env/echo)、外部命令(ls/ps等)、环境变量管理(继承与导出),完全遵循 Linux Shell 的核心工作逻辑。通过亲手实现,你会彻底明白 “输入一条命令后,Shell 到底在做什么”。 一、先搞懂:Shell 的本质是 “命令管家” 在写代码前,

By Ne0inhk
老 MacBook 别扔!装 Linux 部署 OpenClaw 变身 24h 服务器

老 MacBook 别扔!装 Linux 部署 OpenClaw 变身 24h 服务器

老 MacBook 别扔!装 Linux 部署 OpenClaw 变身 24h 服务器 很多用户手中都有老款的 MacBook,这些设备虽然已经不适合作为主力办公电脑,但它们的性能依然足以运行 OpenClaw 本地 AI 服务。本文将详细介绍如何将老款 MacBook 改造为 24 小时运行的 OpenClaw 服务器。 一、硬件评估 1.1 老款 MacBook 型号支持 型号CPU内存存储兼容性推荐度MacBook Pro 2012 (13寸)i5-3210M8GB256GB SSD良好⭐⭐⭐MacBook Pro 2013 (13寸)i5-4258U8GB256GB SSD良好⭐⭐⭐⭐MacBook Pro 2014 (13寸)i5-4278U<

By Ne0inhk