FX-数组的使用
1一维数组
1.1一维数组的创建和初始化
1.1.1数组的创建
//代码1
int arr1[10];
char arr2[10];
float arr3[1];
double arr4[20];
//代码2
//用宏定义的方式
#define X 3
int arr5[X];
//代码3
//错误使用
int count = 10;
int arr6[count];//数组时候可以正常创建?
注:数组创建, [] 中要给一个常量才可以,不能使用变量。可以直接用常量,或者使用宏定义。
1.1.2数组的初始化
//1.数组大小和数值个数一致
int arr1[5] = {1,2,3,4,5}; 1 2 3 4 5//2.数组大小大于初始数
int arr2[6] = {1,2,3}; 1 2 3 0 0 0//3.不指定数组大小
int arr3[] = {1,2,3,4}; 1 2 3 4//4.不指定字符数组大小
char arr5[] = {'a','b','c'}; a b c//5.1字符数组存储字符串
char arr6[] = "abcdef"; a b c d e f \0//5.2字符数组的大小和字符串字符个数一致时
char arr6[6] = "abcdef"; a b c d e f
!!这样初始化是有问题的,因为无法正常读取字符串的结束标志('\0'),导致字符串的长度和内容不能得知!!//6.字符数组大小大于字符串中的字符数char arr7[6] = "zxc"; z x c \0 \0 \0
结论
- 数组是具有相同类型的集合,数组的大小(即所占字节数)由元素个数乘以单个元素的大小。
- 数组只能够整体初始化,不能被整体赋值。只能使用循环从第一个逐个遍历赋值。
- 初始化时,数组的维度或元素个数可忽略 ,编译器会根据花括号中元素个数初始化数组元素的个数。
- 当花括号中用于初始化值的个数不足数组元素大小时,数组剩下的元素依次用0初始化。
- 字符型数组在计算机内部用的时对应的ascii码值进行存储的。
- 一般用”“引起的字符串,不用数组保存时,一般都被直接编译到字符常量区,并且不可被修改。
在内存中的存储

1.2一维数组的使用
#include <stdio.h>
int main()
{int arr[10] = { 0 };//数组的不完全初始化//计算数组的元素个数int sz = sizeof(arr) / sizeof(arr[0]);//对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以:int i = 0;//做下标,此时可以是变量for (i = 0; i < 10; i++){arr[i] = i;}//输出数组的内容for (i = 0; i < 10; ++i){printf("%d ", arr[i]);}return 0;
}
注意:
sizeof()操作符用于取长度,以字节为单位。sizeof(数组名)即求的时整个数组的大小。sizeof(首元素)即求数组单个元素大小。用0下标,是因为数组至少存在一个有效元素,所以0下标永远存在。
数组是使用下标来访问的,下标是从0开始。
数组的大小可以通过计算得到。建议采用sizeof(arr)/sizeof(arr[0])这种方式。
1.3一维数组在内存中的存储
#include <stdio.h>
int main()
{int arr[10] = { 0 };int size = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < size; ++i){printf("&arr[%d] = %p\n", i, &arr[i]);}return 0;
}

仔细观察输出的结果,可知随着数组下标的增长,元素的地址,也在有规律的递增。 由此可以得
出结论:数组在内存中是连续存放的。

总结:
- 数组在内存中开辟是线性连续且递增的。
- 在c语言中,任何变量(基本变量,指针变量,结构体变量,数组变量)的空间都是整体开辟,但任何元素的起始地址一定是开辟字节当中最小的。
2.二维数组
2.1二维数组的创建和初始化
2.1.1二维数组的创建
//数组创建
int arr[3][4];//[行数][列数]
char arr[][5];
double arr[2][4];
二维数组创建时,行数可以忽略不写。并且所有维度的数组其第一个方括号的内容可忽略。
2.1.2二维数组的初始化
//数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};
注意:
花括号中的一个花括号代表一个一维数组的初始化。当里面无花括号分组时,按照顺序从第一个开始逐个进行初始化。余下的未赋值的元素用0初始化。
2.2二维数组的使用
二维数组的使用也是通过下标的方式,用双重循环嵌套进行索引使用。
#include <stdio.h>
int main()
{int arr[3][4] = { 0 };int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 4; j++){arr[i][j] = i * 4 + j;}}for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 4; j++){printf("%d ", arr[i][j]);}}return 0;
}
2.3二维数组在内存中的存储
#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;
}

通过结果我们可以分析到,其实二维数组在内存中也是连续存储的。

注意:
- 二维数组在内存的空间布局上,也是线性连续且递增的!!!
- 二维数组本质上也是一维数组,只不过内部元素放的是一维数组。
3.数组作为参数
- 调用函数传参数组时,减少函数传数组时的成本问题(时间和空间)。因为传参时,需要临时拷贝,如果数组过大,可能会浪费资源,严重的话可能栈溢出。
- 数组元素降维成指向数组内部元素类型的指针。
- 对指针加一,加上所指向的类型的大小。
3.1一维数组
#include<stdio.h>void Lisa(int arr[])
{printf("a = %d\n", sizeof(arr));//数组降维成指针后的指针大小,在32位系统下指针都为4字节printf("b = %d\n", sizeof(arr[0]));//数组首元素的大小printf("sz =a / b = %d\n", sizeof(arr) / sizeof(arr[0]));//大小为1printf("arr = %p\n", arr);//数组首元素地址printf("&arr = %p\n", &arr);//指针的地址printf("arr + 1 = %p\n", arr + 1);//下一个元素的地址printf("&arr + 1 = %p\n", &arr + 1);//指针下一项的地址
}int main(void)
{int Shuzu[10] = { 0,1,2,3,4,5,6,7,8,9 };printf("a = %d\n", sizeof(Shuzu));//数组总大小printf("b = %d\n", sizeof(Shuzu[0]));//数组首元素大小printf("sz =a / b = %d\n", sizeof(Shuzu) / sizeof(Shuzu[0]));//数组元素个数printf("Shuzu = %p\n", Shuzu);//数组首元素地址printf("&Shuzu = %p\n", &Shuzu);//代表整个数组,但是地址仍是首元素地址printf("Shuzu + 1 = %p\n", Shuzu + 1);//下一个元素的地址printf("&Shuzu + 1 = %p\n", &Shuzu + 1);//跳过整个数组后紧挨着的地址//此时该地址减去首元素地址等于数组大小printf("\n\n");Lisa(Shuzu);return 0;
}
补充
sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。&数组名,取出的是数组的地址。&数组名,数组名表示整个数组。


总结:
- 形参格式,例如
int arr[ ]或者int *arr,两者等价 - 形参元素个数可被忽略,并且建议忽略(有可能改变了实参的大小,这样比较方便)。或者也可以填写比实参元素个数大的值。
- 用
sizeof()求数组元素个数时,尽量在数组定义时求。因为传参后数组会降维成指针。
3.2二维数组
#include<stdio.h>void Lisa(int arr[][4])
{printf("a = %d\n", sizeof(arr));//数组降维成指针后的指针大小,在32位系统下指针都为4字节printf("b = %d\n", sizeof(arr[0][0]));//数组首元素的大小printf("sz =a / b = %d\n", sizeof(arr) / sizeof(arr[0][0]));//大小为1printf("arr = %p\n", arr);//数组首元素地址printf("arr + 1 = %p\n", arr + 1);//下一个元素的地址printf("&arr = %p\n", &arr);//指针的地址printf("&arr + 1 = %p\n", &arr + 1);//指针下一项的地址
}int main(void)
{int Shuzu[3][4] = { 0,1,2,3,4,5,6,7,8,9 };printf("a = %d\n", sizeof(Shuzu));//数组总大小printf("b = %d\n", sizeof(Shuzu[0][0]));//数组首元素大小printf("sz =a / b = %d\n", sizeof(Shuzu) / sizeof(Shuzu[0][0]));//数组元素个数printf("Shuzu = %p\n", Shuzu);//数组首元素地址printf("Shuzu + 1 = %p\n", Shuzu + 1);//下一个元素的地址,这时其内部元素的一维数组printf("&Shuzu = %p\n", &Shuzu);//代表整个数组,但是地址仍是首元素地址printf("&Shuzu + 1 = %p\n", &Shuzu + 1);//跳过整个数组后紧挨着的地址//此时该地址减去首元素地址等于数组大小printf("\n\n");Lisa(Shuzu);return 0;
}


形参格式,例如:int arr[][4]或者int (*arr)[4],这里为指向具有四个整型元素的一维数组的数组指针。除了第一个中括号里的数字可以省,后面的中括号的内容不能省略,因为下标是数组类型的一部分,省略掉就不明确其类型。
注意:
看待所有的数组时,都将它看作一维数组,只不过其内部元素不一样,例如:三维数组其内部元素为二维数组,而二维数组也是有一维数组组成,都是线性连续且相等的。
4.数组指针和指针数组
- 数组指针:是指针,指向数组。例:
int (*arr)[10] - 指针数组:是数组,数组内容存放的是指针。例:
int *arr[10]
然后,需要明确一个优先级顺序:()>[]>*
所以:
(*p)[n]:根据优先级,先看括号内,则p是一个指针,这个指针指向一个一维数组,数组长度为n,这是“数组的指针”,即数组指针;
*p[n]:根据优先级,先看[],则p是一个数组,再结合*,这个数组的元素是指针类型,共n个元素,这是“指针的数组”,即指针数组。
4.1指针数组
#include<stdio.h>int main(void)
{int *p[4];int arr1[3] = { 1,2,3 };int arr2[4] = { 2,4,6,8 };int arr3[5] = { 0 };int arr4[2] = { 2,2 };p[0] = arr1;p[1] = arr2;p[2] = arr3;p[3] = arr4;printf("%d\n", *(p[0] + 1));printf("%d\n", *(p[1] + 1));printf("%d\n", *(p[2] + 1));printf("%d\n", *(p[3] + 1));return 0;
}

首先,对于语句int*p[4],因为[ ]的优先级要比*要高,所以 p 先与[ ]结合,构成一个数组的定义,数组名为 p,而int*修饰的是数组的内容,即数组的每个元素。也就是说,该数组包含 4 个指向int类型数据的指针,如图所示,因此,它是一个指针数组。

4.2数组指针
#include<stdio.h>int main(void)
{int Shuzu[3][4] = { 0,1,2,3,4,5,6,7,8,9,0,0 };int(*arr)[4] = Shuzu;for (int i = 0;i < 3;i++){for (int j = 0;j < 4;j++){printf("arr[%d][%d]=%d ", i,j,arr[i][j] );}printf("\n");}return 0;
}

其次,对于语句int(*arr)[4],“( )”的优先级比[ ]高,*号和 arr 构成一个指针的定义,指针变量名为 arr,而 int 修饰的是数组的内容,即数组的每个元素。也就是说,arr 是一个指针,它指向一个包含 4 个int类型数据的数组,如图 所示。很显然,它是一个数组指针。

相关文章:
FX-数组的使用
1一维数组 1.1一维数组的创建和初始化 1.1.1数组的创建 //代码1 int arr1[10]; char arr2[10]; float arr3[1]; double arr4[20]; //代码2 //用宏定义的方式 #define X 3 int arr5[X]; //代码3 //错误使用 int count 10; int arr6[count];//数组时候可以正常创建࿱…...
springboot283图书商城管理系统
图书商城管理系统 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本图书商城管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理…...
FFmpeg-- c++实现:音频流aac和视频流h264封装
文章目录 流程api核心代码muxer.hmuxer.cpp aac 和 h264 封装为视频流,封装为c的Muxter类 流程 分配视频文件上下文 int Init(const char *url); 创建流,赋值给视频的音频流和视频流 int AddStream(AVCodecContext *codec_ctx); 写视频流的head int Se…...
单片机烧录方式,JTAG,ISP,SWD,
常见的词汇 参考 ISP:In System Programing,在系统编程 IAP:In Application Programing,在应用编程 ICP:In Circuit Programing,在电路编程 ICSP全称是In Circuit Serial Programming JTAG(Joint Test Act…...
【项目管理后台】Vue3+Ts+Sass实战框架搭建一
项目管理后台 建立项目最好是卸载Vetur 新建.env.d.ts文件安装Eslint安装校验忽略文件添加运行脚本 安装prettier新建.prettierrc.json添加规则新建.prettierignore忽略文件 安装配置stylelint新建.stylelintrc.cjs 添加后的运行脚本配置husky配置commitlint配置husky 强制使用…...
基于python 变配电室运行状态评估与预警系统flask-django-nodejs-php
变配电室电气设备运行状态和环境信息缺乏必要的监测评估预警手段,如有一日遭遇突发情况,将危及电气设备安全稳定运行,易造成设备损坏和电力供应中断[2]。 目前,我国变配电室常采用无人管理的室内站设计方案,长期以来变配电室运维工…...
【自记录】VS2022编译OpenSSL1.0.2u
因为突然要编译一个老工程,老工程里面用到了OpenSSL 1.0.x。 于是官网下载了最后一个1.0.x版本1.0.2u。 1 下载安装Perl 去Perl官网下载即可。 使用vcpkg直接安装也可以,比前者更方便 vcpkg install perl #根据实际路径调整 set PATHD:\vcpkg\downloa…...
ES代替品:轻量级搜索引擎MeiliSearch
痛点 虽然Elasticsearch足够灵活强大、扩展性和实时性也较好。但是对于中小型项目来说,Elasticsearch还是显得有些庞大,对硬件设备的要求也较高。那么,在要求不是很高的情况下,我们可以考虑另一种搜索引擎方案:MeiliSe…...
用C语言打造自己的Unix风格ls命令
在Unix或类Unix操作系统中,ls是一个非常基础且实用的命令,它用于列出当前目录或指定目录下的文件和子目录。下面,我们将通过C语言编写一个简化的ls命令,展示如何利用dirent.h头文件提供的函数接口实现这一功能。 #include "…...
git的起源
开篇一张图: 开源项目linux kernel开发,参与开发与维护者众多。1991至2005年期间绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上。 在2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维…...
软件杯 深度学习 python opencv 火焰检测识别
文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数:3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…...
C# double类型计算精度问题解决
问题:res 的值0.112450000001,精度不对,预期是0.11245 double force112.45; double res force / Math.Pow(10, index * 3); double force112.45; double res force / Math.Pow(10, index * 3); string str res.ToString(&qu…...
基于Springcloud+Vue校园招聘系统 Eureka分布式微服务
以行动研究为主,辅以文献法、教育实验法和个案研究法等方法相结合的研究方法。在研究方法,遵循软件工程中软件生命周期的规则。概括来讲可以划分成三大步:系统规划、系统开发和系统运行维护。将其上述步骤细分下来,可以分为以下8小…...
【NLP笔记】RNN总结
文章目录 经典RNN单向RNN双向RNNDeep RNNRNN特性总结 变体RNNLSTMGRU 参考及转载内容: 循环神经网络(RNN)深度学习05-RNN循环神经网络完全理解RNN(循环神经网络) 传统的CNN(Covolutional Neural Network&am…...
[c++]内存管理
1. C/C内存分布 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() { static int staticVar 1; int localVar 1; int num1[10] { 1, 2, 3, 4 }; char char2[] "abcd"; const char* pChar3 "abcd"; …...
k8s通过编排文件,实现服务的滚动更新
k8s通过编排文件,实现服务的滚动更新 apiVersion: apps/v1 kind: pod metadata:name: ‘servicename’labels:app: ‘servicename’ spec:replicas: 4 ##pod启动数量最少为2,不然滚动更新无意义strategy:type: RollingUpdate ##设置类型为滚动更新以及…...
安卓面试题多线程 96-100
96. 简述notify()和notifyAll()有什么区别 ?notify可能会导致死锁,而notifyAll则不会任何时候只有一个线程可以获得锁,也就是说只有一个线程可以运行synchronized 中的代码 使用notifyall,可以唤醒 所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一…...
第二十六章 配置 Web Gateway 的默认参数
文章目录 第二十六章 配置 Web Gateway 的默认参数网络网关实例主机名最大连接数最大缓存大小网络服务器 ID Cookie 第二十六章 配置 Web Gateway 的默认参数 本页介绍如何通过 Web Gateway 管理页面配置 IRIS Web Gateway 的默认参数。其他文章介绍了如何配置服务器和应用程序…...
npm i安装依赖报错,但是cnpm i 却安装成功
问题描述:在a项目中npm i 安装依赖时发生以上报错,但是cnpm i 却成功,而且在其他项目中npm i 安装其他项目依赖也能成功.... 解决办法:删除项目中package-lock.json文件后再npm i 即可...
C语言经典算法-9
文章目录 其他经典例题跳转链接46.稀疏矩阵47.多维矩阵转一维矩阵48.上三角、下三角、对称矩阵49.奇数魔方阵50.4N 魔方阵51.2(2N1) 魔方阵 其他经典例题跳转链接 C语言经典算法-1 1.汉若塔 2. 费式数列 3. 巴斯卡三角形 4. 三色棋 5. 老鼠走迷官(一)6.…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
