C语言基础之数组

news2024/9/29 18:20:29

上一篇讲述了C语言函数的使用,本文讲述数组的相关概念,通过一维数组、二维数组、数组越界等详细讲解数组相关的具体内容,以辅助读者了解并掌握数组相关概念。

一维数组

一维数组的定义与创建

若无数组,我们要存储一堆类型相同的数值,就要创建一系列类型相同的变量,这样带来了代码复杂度。因此C语言给出了数组类型。C语言中数组的定义是:数组是一组相同类型元素的集合。

一维数组的创建:type_t  arr_name [const_n];  其中type_t 是指数组的元素类型,const_n 是一个常量表达式,用来指定数组的大小。

        注:对于数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。但在C99标准中支持了变长数组的概念,即数组的大小可以使用变量指定,但是这样的数组不能初始化。

一维数组的初始化和使用

        数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
        当然数组在创建的时候如果想不指定数组的确定的大小就必须得初始化,数组的元素个数根据初始化的内容来确定

#include<stdio.h>
void print_arr(int* arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr1[10] = { 1,2,3,4,5 };//不完全初始化,剩余元素都是0
	int arr2[10] = { 0 };//不完全初始化,剩余元素都是0
	int arr3[5] = { 2,3,4,5,6 };//完全初始化

	printf("print arr 1:->");
	print_arr(arr1, 10);
	printf("print arr 2:->");
	print_arr(arr2, 10);
	printf("print arr 3:->");
	print_arr(arr3, 5);

	char str[] = "hello world";
	return 0;
}

        由上述代码可知不完全初始化,指的是局部初始化,即对数组按从前往后(也可以说是,从低地址到高地址)对元素依次赋初值,剩余的元素则默认为0。所以对于 int arr2[10] = { 0 }; 这种,不要认为是将全部元素的初值附为0,实则是只将第一个元素赋初值为0,其余元素默认为0。
        而完全初始化,则更容易理解,即将数组中的元素全部赋初值。

定义数组时,[]中可以省略数组长度,C语言会自动计算数组长度。

数组的使用:对于数组的使用又一个操作符  [],即下标引用操作符。有了下标访问操作符,我们就可以轻松的访问到数组的元素了。

举个例子:

总结:

1.数组是通过下标进行访问的,下标是从0开始。

2.数组的长度是可以通过计算得到的。

一维数组的输入

明⽩了数组的访问,当然我们也根据需求,⾃⼰给数组输⼊想要的数据,如下:
#include<stdio.h>
int main()
{
	int arr[10];
	for (int i = 0; i < 10; i++)
	{
		scanf("%d", &arr[i]);
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

一维数组在内存中的存储

数组在内存中是怎样存储的呢?是离散的?还是连续的?答案是连续存储的。一起来看看下面这段代码中数组元素在内存中的存放地址吧。

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

小Tips

1.%p------用来打印数据存放的地址,输出地址的形式一般是以16进制输出的

2.十六进制对应十进制与二进制如下表

十六进制数字01234567
十进制值01234567
二进制值00000001001000110100010101100111
十六进制数字89ABCDEF
十进制值89101112131415
二进制值10001001101010111100110111101111

从输出的结果分析,数组随着下标的增长,地址从小到大变化,并且每两个相邻的元素之间相差4所以我们得出结论:数组在内存中是连续存放的。这就 为后期我们使⽤指针访问数组奠定了基础(在讲指针的时候我们在再讲,这⾥暂且记住就⾏)。

二维数组

二维数组的创建和初始化

二维数组的创建和一维数组类似,只不过多了行列之分。创建语法如下:

type arr_name[常量值1][常量值2]
在创建变量或者数组的时候,给定⼀些初始值,被称为初始化。
那⼆维数组如何初始化呢?像⼀维数组⼀样,也是使⽤⼤括号初始化的。话不多说,直接上代码:
#include<stdio.h>
int main()
{
	int arr1[4][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7},{4,5,6,7,8} };
	int arr2[4][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,7, 4,5,6,8 }; // 不完全初始化,填满才换行
	int arr3[4][5] = { { 1,2,3 }, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8 };
	int arr4[4][5] = { {1,2,3,},{2,3,4,5},{3,4,5,6,7},{4,5} };

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

	return 0;
}

        上述代码,arr1数组是最标准的初始化,对于arr1数组中每行元素的初始化,都再用{}括起来,使代码更清晰明了。
        对于arr2数组的初始化,又称为不完全初始化,即对每行元素赋初值时不用{}括起来,那这时元素的赋值情况是怎样的呢?这些值会从数组第一行元素开始进行填充,当第一行的元素填满后再继续给下一行元素赋值,如果最后赋值完还有元素未被初始化,则这些元素默认为0。(见如下调试arr2数组中的元素值)

 arr数组的初始化,是非常特殊的初始化方式。行是可以省略的,但列不能省略。该初始化方式可以借助下图理解。

对于一维数组来说,在初始化时无需知道它有多少个元素。但对于二维数组而言,不需要知道二维数组有多少行,但需要知道二维数组的列数以确定一行有多大。

二维数组的使用

二维数组的使用与一维数组类似,均通过下标来访问数组中的元素,并且行和列的下标均是从0开始的。

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

二维数组在内存中的存储

 二维数组在内存中的存储是怎么样的呢?你是不是认为一行内部的元素是连续存储的,而行与行之间的存储是离散的。然而实际是,二维数组在内存中的存储和一维数组一样,无论是行内部还是行之间都是连续存储的。看看下面这段代码吧。

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

仔细观察可知一行内部的元素是连续存储的。我们重点观察一行末尾元素与下一行首元素之间的地址间隔:arr[0][2]地址的最后两位为D0,arr[1][0]地址的最后两位为D4,两者之间的地址大小相差4个字节,因此二维数组中,行与行之间也是连续存储的,也是从低地址向高地址存储。(如下图)

数组越界

        1. 数组的下标是有范围限制的。
        2. 数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
        3. 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
        4. C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以我们在写代码时,最好自己做越界的检查。

看一个经典例子

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

运行这段代码,会发现它死循环。下面解释一下这段代码为什么会发生死循环。

数组名的理解

 数组名通常情况下是数组首元素的地址。但是有2个例外:
        1. sizeof(数组名),数组名单独放在sizeof()内部,这里的数组名表示整个数组,计算的是整个数组的大小。
         2. &数组名,这里的数组也表示整个数组,这里取的是整个数组的地址。
        除此之外,遇到的所有数组名都表示数组首元素的地址。

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6 };
	//数组首元素地址
	printf("%p\n", arr);
	printf("%p\n", arr + 1);
	printf("\n");

	printf("%p\n", &arr[0]);
	printf("%p\n", &arr[0] + 1);
	printf("\n");

	//数组的地址
	printf("%p\n", &arr);
	printf("%p\n", &arr + 1);
	printf("\n");

	//整个数组的大小
	printf("%zd\n", sizeof(arr));
	return 0;
}

如果我们取首元素的地址&arr[0],再对&arr[0]+1,会发现两者之间的地址相差4,即只跳过了一个整型元素的大小,而假如我们对数组名取地址(&arr),再进行&arr+1,地址的最后两位由A8变成了D0,经计算两个相差40个字节,即整个arr数组的大小。故&数组名,取的是整个数组的地址。

本文就介绍到这里啦,我们下期再见! 

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

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

相关文章

osalTaskREC_t ‘REC’缩写的含义

osalTaskREC_t中‘REC’缩写的含义。 在osal中定义了 osalTimerRec_t&#xff0c; osalTaskRec_t 结构体&#xff0c;那么osal源码中类型名 osalTaskREC_t中‘REC’缩写的含义是什么&#xff1f; 查了下往上资料&#xff0c;rec应该是 Record&#xff08;记录&#xff09;’的…

AI大模型之旅-最强开源文生图工具Stable Diffusion WebUI 教程

1.1克隆 Automatic1111 的 GitHub 仓库 在你想安装 Web UI 的文件夹路径下执行 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui 这将会克隆整个仓库到本地。 这里会默认访问 https://huggingface.co/ 下载 因此需要魔法 1.2 进入仓库目录 cd stable-di…

手机改IP地址怎么弄?全面解析与操作指南

在当今数字化时代&#xff0c;IP地址作为设备在网络中的唯一标识&#xff0c;其重要性不言而喻。有时候&#xff0c;出于隐私保护、网络访问需求或其他特定原因&#xff0c;我们可能需要更改手机的IP地址。然而&#xff0c;对于大多数普通用户来说&#xff0c;如何操作可能还是…

Xshell调用powershell连接Teleport

公司最近切换telport管理SSH的连接访问。配置完成后&#xff0c;通过powershell可能远程访问。但是powershell缺少session管理功能&#xff0c;每次连接都记不住远程IP&#xff0c;很是头疼。 利用Xshell的管理能力是否可行&#xff1f;那是相当可行。 首先&#xff0c;新建se…

环境变量配置文件

环境变量配置文件 系统级配置文件 /etc/profile 系统范围的配置文件&#xff0c;适用于所有用户的登录 shell。 定义了系统级别的环境变量&#xff0c;并调用其他配置文件&#xff08;如 /etc/bash.bashrc&#xff09;。 /etc/bash.bashrc 非登录 shell 的全局配置文件。 在系…

Java异步编程:初学者快速入门到精通指南

异步编程简介 异步编程允许程序在执行某些操作&#xff08;如网络请求、文件I/O等&#xff09;时不被阻塞&#xff0c;能够继续执行其他任务。这不仅可以提高程序的响应性&#xff0c;还能提升资源的利用率。 为什么选择Java进行异步编程&#xff1f; Java提供了多种异步编程…

Echarts折线图的末尾部分线条虚线

原理&#xff1a;等于画了两条线&#xff0c;一条实线一条虚线&#xff1b;把实线的最后的值给虚线&#xff1b;再将提示框进行过滤&#xff0c;防止多个点以及值为空的情况 初步实现参考&#xff1a; option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, …

《低空经济:文旅行业的新引擎 》

《低空经济&#xff1a;文旅行业的新引擎 》 一、低空经济与文旅行业的融合态势 低空经济作为新兴经济形态&#xff0c;正与文旅行业深度融合&#xff0c;为文旅发展带来新机遇。 近年来&#xff0c;随着科技的不断进步和人们对旅游体验的不断追求&#xff0c;低空经济与文旅…

js列表数据时间排序和取唯一值

1.取唯一值[...new Set(array)] const array [1, 2, 3, 2, 4, 5, 3, 5]; // 使用Set去除重复元素 const uniarray [...new Set(array)]; console.log(uniarray); // 输出: [1, 2, 3, 4, 5] 2.排序 var u [1,3,2,5,4]; var uu u.sort(); console.log(uu); var u [1,3…

ACL 2023--MetaAdapt: 通过元学习实现领域自适应的少量样本虚假信息检测

https://github.com/Yueeeeeeee/MetaAdapt 随着社交媒体上出现的新话题&#xff08;例如COVID-19&#xff09;成为虚假信息传播的来源&#xff0c;克服原始训练领域&#xff08;即源领域&#xff09;与这些目标领域之间的分布变化&#xff0c;仍然是虚假信息检测中的一项复杂任…

金三银四:20道前端手写面试题

文章目录 一、前言二、题目1. 防抖节流解读 2.一个正则题3. 不使用a标签&#xff0c;如何实现a标签的功能4. 不使用循环API 来删除数组中指定位置的元素&#xff08;如&#xff1a;删除第三位&#xff09; 写越多越好5. 深拷贝解读 6. 手写call bind applycall 解读apply 解读 …

Chrome无法拖入加载.crx扩展文件(以IDM为例)

问题原因&#xff1a;新版本的Chrome浏览器已不支持加载.crx文件 解决办法&#xff1a;将.crx文件压缩为.zip文件&#xff0c;解压缩后再加载到Chrome中 以IDM的.crx文件作为示例&#xff1b; IDM的.crx文件位于C:\Program Files (x86)\Internet Download Manager; 将IDMGCE…

计算机毕业设计 C语言学习辅导网站的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

记一次实战中对Ruoyi系统的渗透

前言 最近碰到比较多Ruoyi的站&#xff0c;ruoyi的话漏洞还是比较多的&#xff0c;这里就分享一下自己渗透的一些案例吧&#xff0c;方便大家参考学习 首先声明 文章中涉及的敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权…

解决:使用layui.treeTable.updateNode,更新表格数据后,done里面的事件丢失问题

1. 背景 在给树形表格添加行点击事件&#xff0c;并且只更新当前行数据。 treeTable.updateNode("SpeProjListId", result.LAY_DATA_INDEX, result);更新数据后&#xff0c;点击事件失效。 1. 给字段绑定事件&#xff1a; class"link_a link_style" , {…

基于Spring3.0实现AOP的小案例

前言 AOP&#xff08;Aspect Oriented Programming&#xff09;即面向切面编程&#xff0c;是一种通过预编译方式和运行期间动态代理实现程序功能统一维护的技术。针对功能增强的描述&#xff0c;可以理解为&#xff1a;“AOP允许在不修改源代码的情况下&#xff0c;通过定义切…

Java异步编程:从入门到精通

在现代编程实践中&#xff0c;异步编程已成为提升程序性能和用户体验的关键技术。Java&#xff0c;作为一种成熟且广泛使用的编程语言&#xff0c;提供了多种实现异步编程的方法。本文将带你从异步编程的基础知识入手&#xff0c;逐步深入到Java中的异步编程实践。 异步编程简介…

SQL常用数据过滤 - EXISTS运算符

SQL查询中的EXISTS运算符用于检查查询子句是否存在满足特定条件的记录&#xff0c;如果有一条或者多条记录存在&#xff0c;则返回True&#xff0c;否则返回False。 语法结构 SELECT column_name(s)FROM table_nameWHERE EXISTS(SELECT column_name FROM table_name WHERE co…

基于两分支卷积和 Transformer 的轻量级多尺度特征融合超分辨率网络 !

当前的单图像超分辨率&#xff08;SISR&#xff09;算法有两种主要的深度学习模型&#xff0c;一种是基于卷积神经网络&#xff08;CNN&#xff09;的模型&#xff0c;另一种是基于Transformer的模型。前者利用不同卷积核大小的卷积层堆叠来设计模型&#xff0c;使得模型能够更…

SOLID原则:现代软件架构的永恒基石

关注TechLead&#xff0c;复旦博士&#xff0c;分享云服务领域全维度开发技术。拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;复旦机器人智能实验室成员&#xff0c;国家级大学生赛事评审专家&#xff0c;发表多篇SCI核心期刊学术论文&#xff0c;阿里云认…