C语言数组介绍

文章目录

  • 一、数组的概念
  • 二、一维数组
    • 1.一维数组的创建
    • 2.一维数组的初始化
    • 3.数组的类型
    • 4.一维数组的使用
    • 5.一维数组在内存中的存储
    • 6.sizeof计算数组元素个数
  • 三、二维数组
    • 1.二维数组的概念
    • 2.二维数组的创建
    • 3.二维数组的初始化
    • 4.二维数组的使用
    • 5.二维数组的输入和输出
    • 6.二维数组在内存中的存储
    • 7.二维数组中对于数组名的理解

一、数组的概念

数组一组相同类型元素的集合;从这个概念中我们就可以发现2个有价值的信息:
数组中存放的是1个或者多个数据,但是数组元素个数不能为0。
数组中存放的多个数据,类型是相同的。
数组分为一维数组和多维数组,多维数组一般比较常见的是二维数组。

二、一维数组

1.一维数组的创建

一维数组创建的语法如下:
在这里插入图片描述存放在数组中的值被称为数组的元素,数组在创建的时候可以指定数组的大小和数组的元素类型。
type指定的是数组中存放的数据的类型,可以是: char、short、int、float等,也可以自定义的类型。
arr_name指的是数组的名字,这个名字根据实际情况,起的有意义就行。(注意不要跟关键字重名)
[ ]中的常量值是用来指定数组的大小的(元素个数),数组的大小根据实际的需求指定就行。
需要注意在创建数组时,[ ]中要给的是一个常量才可以,不能给变量。[ ]可以直接使用常量,常量表达式或者宏定义都可以。示例:

#include<stdio.h>
#define NUM 6
int main()
{
    int arr1[10];
    int arr2[2+3];
    char ch[NUM];
    return 0;
}

2.一维数组的初始化

在创建数组的同时,给一些初始值,这种就称为数组的初始化。那数组如何初始化呢?数组的初始化一般使用大括号,将数据放在大括号中:

//完全初始化
int arr1[5]={1,2,3,4,5};

//不完全初始化
int arr2[5]={1};//第一个元素初始化为1,剩下的元素默认初始化为0

3.数组的类型

数组也是有类型的,数组算是一种自定义类型,去掉数组名留下的就是数组的类型。例如:

int arr[10];
char ch[5];

arr数组的类型为int [10],ch数组的类型为char [5]。

4.一维数组的使用

学习了一维数组的基本语法,一维数组可以存放数据,存放数据的目的是对数据进行操作,那我们如何使用一维数组呢?
(1)数组下标
C语言规定数组是有下标的,下标是从0开始的,假设数组有n个元素,最后一个元素的下标是n-1,下标就相当于数组元素的编号,如下:

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

在这里插入图片描述在C语言中,对于数组的访问提供了一个操作符 [ ],这个操作符叫:下标引用操作符
有了下标引用操作符,我们就可以轻松的访问到数组的元素了,比如我们访问下标为6的元素,我们就可以使用arr[6],想要访问下标是4的元素,就可以使用arr[4],如下代码:

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

运行结果:
在这里插入图片描述(2)数组元素的打印
如果想要打印数组的元素在屏幕上,就用for循环产生0~9的下标,使用下标访问数组的元素即可:

#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 ", arr[i]);
	}
	return 0;
}

运行结果:
在这里插入图片描述(3)数组元素的输入
可以根据自己的需要,用scanf函数给数组输入值,存入到数组中。给数组输入想要的数据:

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		scanf("%d", &arr[i]);
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

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

5.一维数组在内存中的存储

一维数组在内存中是怎样存储的呢?我们通过下面一段代码来看:

#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("&arr[%d]=%p\n",i, &arr[i]);
	}
	return 0;
}

运行结果:
在这里插入图片描述从输出的结果可以发现,数组随着下标的增长,地址是由小到大变化的,并且我们发现每相邻两个元素之间相差4(因为一个整型是4个字节)。所以我们得出结论:数组在内存中是连续存放的

6.sizeof计算数组元素个数

在遍历数组的时候,我们经常想知道数组的元素个数,那C语言中有办法使用程序计算数组元素个数吗?答案是有的。通过sizeof可以求元素个数。其实sizeof是一个操作符,是用来计算类型或者变量的大小的(单位字节)。sizeof可以用来计算数组的大小:

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%d\n", sizeof(arr));
	return 0;
}

运行结果:
在这里插入图片描述输出的结果为40,计算的是整个数组所占内存空间的大小,单位是字节(数组名单独放在sizeof中,计算的是整个数组的大小)。又因为数组中所有元素的类型是相同的,所以只要计算出一个元素所占字节的个数,那数组的元素个数就可以计算出来了。我们通常选择计算第一个元素的大小:

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	//计算数组中第一个元素的大小
	printf("%d\n", sizeof(arr[0]));

	//计算数组的元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", sz);
	return 0;
}

运行结果:
在这里插入图片描述可以看到,第一个元素的大小为4(字节),数组的元素个数为10。以后在代码中需要数组元素个数的地方就不用固定写死了,这种计算数组元素个数的方式,不管数组怎么变化,计算出的大小也会随着变化。

三、二维数组

1.二维数组的概念

上面学习的数组叫一维数组,数组的元素都是内置类型的。如果把一维数组做为数组的元素,这时候就是二维数组。二维数组作为数组元素的数组被称为三维数组,二维数组以上的数组统称为多维数组
在这里插入图片描述

2.二维数组的创建

如何创建二维数组呢?语法形式是什么?如下:
在这里插入图片描述例如:

int arr[3][5];
double data[2][7];

上面代码的第一行,就是一个整型的二维数组。其中:
3表示有3行;5表示列数,即每一行有5个元素。
int表示数组的每个元素是整型类型。
arr是数组名,可以根据自己的需要指定名字(注意不能和关键字重名)。
第二行是一个双精度浮点型二维数组。

3.二维数组的初始化

在创建数组的同时,给一些初始值,就叫数组的初始化。二维数组的初始化也跟一维数组类似,使用大括号初始化:
(1)不完全初始化

int arr1[3][5]={1,2};
int arr2[3][5]={0};

在屏幕上打印这两个数组:
在这里插入图片描述可以看到上面对于两个二维数组不完全初始化的打印结果,对于arr1数组,只初始化了两个元素,即从第一行的一维数组的第一个元素开始,从左往右依次初始化。如果一行的元素值给够了,就会从下一行一维数组的第一个元素开始从左往右初始化。对于没有给到值的元素会默认初始化为0。arr2数组只初始化了第一行的第一个元素为0,其余元素默认初始化为0。如下:
在这里插入图片描述(2)完全初始化

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

在屏幕上打印arr3数组的内容:
在这里插入图片描述完全初始化就很好理解了:在创建二维数组的同时,对二维数组的所有元素都给一个初始值,就叫作完全初始化,对于{ }里的值,会从左往右,依次给到二维数组对应的元素。如果一行的值够了,就会从数组下一行的一维数组的第一个元素开始从左往右初始化。
(3)按照行进行初始化
什么叫按照行进行初始化?其实就是按照二维数组的每个一维数组进行初始化,在二维数组的大括号{ }内部,会明确的给出每个一维数组,对每个一维数组进行初始化。例如:

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

打印出数组的内容,如下图样式:
在这里插入图片描述可以看到上面的二维数组按照行进行初始化,在大括号的内部明确给出了二维数组的每个一维数组,因为一维数组的内容也是用大括号括起来的。所以在二维数组里对每一行进行初始化是遵循一维数组的初始化原则的。
(4)数组初始化时可以省略行,但不能省略列
二维数组在创建并初始化时,可以省略行数,但是不能省略列数:

int arr5[][5]={1,2,3};
int arr6[][5]={1,2,3,4,5,6,7};
int arr7[][5]={{1,2},{3,4},{5,6}};

上面三个数组得到数组形式会是:
在这里插入图片描述可以看到当数组给出列数却没有给出行数时,系统会根据你大括号里初始化数据的多少,自动计算数组的行数,确定数组是一个什么类型的数组。

4.二维数组的使用

二维数组的访问也是使用下标的形式进行的,二维数组是有行和列的,只要锁定了行和列就能唯一锁定数组中的一个元素。C语言规定:二维数组的行是从0开始的,列也是从0开始的,如下所示:

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

在这里插入图片描述上图中,最左侧的灰色数字表示行号,最上面一行的橙色数字表示列号,可以发现下标都是从0开始。比如:行号为2,列号为3的元素,就是6:

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

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

5.二维数组的输入和输出

上面讲过一维数组的访问,是通过下标进行的,用for循环产生对应的下标。二维数组也是一样的,也是通过下标来访问,只不过二维数组有行和列两个下标,如果要对二维数组进行输入输出的话,就要使用两个for循环,外层循环控制每一行的循环,内层的循环控制每一行里所有元素个数(列数)的循环。比如我们要输入和打印上面的arr数组在屏幕上,行的范围是0~2,列的范围是0~4,用两个for循环产生相应的行和列号:

#include<stdio.h>
int main()
{
	int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };
	int i = 0;
	//输入
	for (i = 0; i < 3; i++) //产生行号
	{
		int j = 0;
		for (j = 0; j < 5; j++) //产生列号
		{
			scanf("%d", &arr[i][j]); //输入数据
		}
	}
	//输出
	for (i = 0; i < 3; i++) //产生行号
	{
		int j = 0;
		for (j = 0; j < 5; j++) //产生列号
		{
			printf("%d ", arr[i][j]); //输出数据
		}
		printf("\n");
	}
	return 0;
}

输入数据后得到的结果:
在这里插入图片描述

6.二维数组在内存中的存储

与一维数组一样,如果想知道二维数组在内存中的存储方式,我们也是可以打印出数组所有元素的地址的。代码如下:

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

运行结果:
在这里插入图片描述从输出的结果来看,每一行内部的元素两两都是相邻的,地址之间相差4个字节,跨行位置处的两个元素(如: arr[0][4]和arr[1][0])之间也是差4个字节,所以得到的结论是:二维数组中的每个元素在内存中都是连续存放的

7.二维数组中对于数组名的理解

在二维数组中,数组名表示什么含义?我们之前讲过一维数组的数组名是表示数组首元素的地址,也就是数组中第一个元素的地址。那二维数组的数组名其实也表示数组首元素的地址,但是这个首元素是指那个呢?这里我们要把二维数组看成是一个一维数组。举个例子:

int arr[3][4]={0};

在这里插入图片描述二维数组其实可以看作是由一维数组构成的数组,也就是把每行的一维数组整体看做是一个元素,则二维数组现在就相当于一个一维数组,数组的首元素就是第一行的一维数组,则数组名就是第一行一维数组的地址,它是一个数组指针。就像上面的arr[3][4]数组,数组名arr表示的是第一行一维数组的地址,它是一个 int(*)[4] 类型的数组指针:即 arr==&arr[0]

二维数组去掉列下标部分也是数组名,如下:
在这里插入图片描述数组名表示的是数组首元素的地址。则二维数组去掉列下标后的数组名,如上面的arr[0]、arr[1]和arr[2]分别表示二维数组中每行一维数组的首元素地址,即每个一维数组的第一个元素的地址,类型是int*的指针:arr[0]==&arr[0][0]arr[1]==&arr[1][0]arr[2]==&arr[2][0]
所以在二维数组中要区分开上面的两种数组名,不能混淆,尤其是在sizeof中放有关数组名的各种表达式时,要特别区分上面的两种数组名。

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

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

相关文章

【教学类-50-09】20240505“数一数”图片样式09:数一数(几何图案——透明颜色重叠+纯黑边框+黑框粗细)

背景需求&#xff1a; 【教学类-50-03】20240408“数一数”图片样式03&#xff1a;透明图形与边框不相交&#xff0c;透明图形和其他透明图形重叠-CSDN博客文章浏览阅读867次&#xff0c;点赞28次&#xff0c;收藏25次。【教学类-50-03】20240408“数一数”图片样式03&#xf…

银行ETL-监管报送

1104报表 1104报表主要包括&#xff1a;资产负债&#xff0c;表外业务、流动性风险、贷款质量、投向行业和地区、重点客户等。 1104报表分类 普通报表、机构特色类报表。 反洗钱 大额交易、可疑交易。标签分类&#xff1a;疑似犯罪、疑似毒品、疑似传销。 反洗钱—接口报…

tomcat+maven+java+mysql图书管理系统2-完善项目结构,添加相关依赖

1.创建java目录 接着选择java&#xff0c;回车&#xff0c;则创建成功&#xff0c;成功后在左侧栏能看见 2.修改pom.xml文件,(添加依赖) <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

pandas读取文件导致jupyter内核崩溃如何解决

读取execl文件出现以下问题: str_name "D:\\cao_use\\2017_2021(new).xlsx" train_df pd.read_excel(str_name, usecols[0])崩溃的指示图如下所示: bug原因:读入的文件太大&#xff0c;所需时间过长&#xff0c;在读取的过程中&#xff0c;使用中断按钮暂停会直…

mac监听 linux服务器可视化(Grafana+Promethus+Node_exporter)

Grafana和promethus(普罗米修斯)的安装和使用 监控系统的Prometheus类似于一个注册中心&#xff0c;我们可以只需要配置一个Prometheus,而在其他服务器&#xff0c;只需要安装node_exporter,它们的数据流转就是通过exporter采集数据信息&#xff0c;然后告诉prometheus它的位置…

AI视频教程下载:用 ChatGPT 和 WordPress 创建赚钱网站

您是否有兴趣开设网站&#xff08;博客&#xff09;&#xff0c;但不知道从何入手&#xff1f; 或者您已经开设了网站&#xff08;博客&#xff09;&#xff0c;但难以从中获利&#xff1f; 别找啦&#xff01; 本课程旨在教授您使用 WordPress 创建成功盈利网站&#xff08;博…

OpenCV(五) —— 人脸识别模型训练与 Windows 下的人脸识别

本文主要内容&#xff1a; 如何训练 OpenCV 的人脸识别模型如何在 Windows 下利用 OpenCV 进行人脸识别 1、概述 人脸识别需要人脸模型&#xff08;特征集合&#xff09;的支持&#xff0c;人脸定位的速度与准确度取决于模型。 OpenCV 提供了已经训练好的模型&#xff0c;无…

【莫比乌斯变换-04】求解莫比乌斯变换系数

求解莫比乌斯变换系数 文章目录 一、说明二、如何确定双线性变换系数2.1 变换基本形式2.2 通过三点确定 三、一般情况的变换3.1 最简单的情况&#xff1a;无穷大3.2 处理无穷大 四、Python 代码 一、说明 上一篇文章是对双线性变换的视觉介绍&#xff0c;又名莫比乌斯变换或分…

ThreeJS:补间动画与Tween.JS

补间动画 补间动画指的是做FLASH动画时&#xff0c;在两个关键帧中间需要做“补间动画”&#xff0c;才能实现图画的运动&#xff1b;插入补间动画后两个关键帧之间的插补帧是由计算机自动运算而得到的。 ——摘自《百度百科&#xff1a;补间动画_百度百科》 Tween.js Tween.js…

Python-VBA函数之旅-oct函数

目录 一、oct函数的常见应用场景 二、oct函数使用注意事项 三、如何用好oct函数&#xff1f; 1、oct函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;神奇夜光杯-CSDN博客 一、oct函数的常见应用场景 oc…

W801学习笔记十七:古诗学习应用——上

硬件驱动以及软件架构大体上已经完成&#xff0c;尚存一些遗漏之处&#xff0c;后续会寻找合适的时机进行补充。自此章起&#xff0c;将正式迈入软件应用阶段&#xff0c;尤其是游戏开发领域。 关于第一个应用&#xff0c;此前已有一些构想&#xff1a; 其一&#xff0c;随机…

IO流-其他流:数据流,序列化流

import java.io.DataOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream;public class DataOutputStream1 {public static void main(String[] args) {//创建一个数据输出流包装一个低级的字节输出流try (DataOutputStream dosnew DataOutp…

9.3.k8s的控制器资源(deployment部署控制器)

目录 一、deployment部署控制器概念 二、deployment资源的清单编写 三、小结 功能 使用场景 原理 四、deployment实现升级和回滚 1.编辑deployment资源清单&#xff08;v1版本&#xff09; 2.创建service资源用于访问 ​编辑 3.修改deploy清单中pod镜像版本为V2 4…

「C/C++ 01」scanf()与回车滞留问题

目录 〇、scanf()接收用户输入的流程 一、回车的缓冲区滞留问题是什么&#xff1f; 二、为什么&#xff1f; 三、四个解决方法&#xff1a; 1. 在前面的scanf()中加上\n 2. 在scanf("%c")中添加空格 3. 使用getchar()来吸收回车 4. 使用fflush()清空缓冲区 〇、scan…

2.spring security 简单入门

创建springboot 项目&#xff0c;引入spring security坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--spring security坐标--><dependency&g…

leecode每日一练

我一开始的思路也是dp&#xff0c;但是转移方程想错了&#xff0c;这个题目转移方程应该是dp[i] max(dp[i-2]nums[i],dp[i-1]) class Solution { public:int rob(vector<int>& nums) {int len nums.size();vector<int> dp(len);int ans 0;if(len>1)dp[0]…

IoTDB 入门教程 基础篇①——时序数据库为什么选IoTDB ?

文章目录 一、前文二、性能排行第一三、完全开源四、数据文件TsFile五、乱序数据高写入六、其他七、参考 一、前文 IoTDB入门教程——导读 关注博主的同学都知道&#xff0c;博主在物联网领域深耕多年。 时序数据库&#xff0c;博主已经用过很多&#xff0c;从最早的InfluxDB&a…

《Fundamentals of Power Electronics》——脉宽调制器建模

下图给出了一个简单脉宽调制器电路的原理图。 脉宽调制器电路产生一个用于指令转换器功率管导通和关断的逻辑信号δ(t)。该逻辑信号δ(t)是周期性的&#xff0c;其频率为fs&#xff0c;占空比为d(t)。脉宽调制器的输入是一个模拟控制信号vc(t)。脉宽调制器的作用是产生一个与模…

观测与预测差值自动变化系统噪声Q的自适应UKF(AUKF_Q)MATLAB编写

简述 基于三维模型的UKF&#xff0c;设计一段时间的输入状态误差较大&#xff0c;此时通过对比预测的状态值与观测值的残差&#xff0c;在相应的情况下自适应扩大系统方差Q&#xff0c;构成自适应无迹卡尔曼滤波&#xff08;AUKF&#xff09;&#xff0c;与传统的UKF相比&…

【人工智能Ⅱ】实验5:自然语言处理实践(情感分类)

实验5&#xff1a;自然语言处理实践&#xff08;情感分类&#xff09; 一&#xff1a;实验目的与要求 1&#xff1a;掌握RNN、LSTM、GRU的原理。 2&#xff1a;学习用RNN、LSTM、GRU网络建立训练模型&#xff0c;并对模型进行评估。 3&#xff1a;学习用RNN、LSTM、GRU网络做…