当前位置: 首页 > news >正文

C语言数组【详解】

在这里插入图片描述

数组

  • 1. 一维数组的创建和初始化
    • 1.1 数组的创建
    • 1.2 数组的初始化
    • 1.3 一维数组的使用
    • 1.4 一维数组在内存中的存储
  • 2. 二维数组的创建和初始化
    • 2.1 二维数组的创建
    • 2.2 二维数组的初始化
    • 2.3 二维数组的使用
    • 2.4 二维数组在内存中的存储
  • 3. 数组越界
  • 4. 数组作为函数参数
    • 4.1 冒泡排序函数的错误设计
    • 4.2 数组名是什么?
    • 4.3 冒泡排序函数的正确设计

1. 一维数组的创建和初始化

1.1 数组的创建

数组是一组相同类型元素的集合。
数组的创建方式:

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

数组创建的实例:

char arr3[10];
float arr4[1];
double arr5[20];

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

1.2 数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
看代码:

int arr1[10] = {1,2,3};
int arr2[] = {1,2,3,4};
int arr3[5] = {1,2,3,4,5};
char arr4[3] = {‘a’,98, ‘c’};
char arr5[] = {‘a’,‘b’,‘c’};
char arr6[] = “abcdef”;

数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。
但是对于下面的代码要区分,内存中如何分配

char arr1[ ] = “abc”;//包含/0
char arr2[3] = {‘a’,‘b’,‘c’};//不包含/0

1.3 一维数组的使用

对于数组的使用我们之前介绍了一个操作符: [ ] ,下标引用操作符。它其实就数组访问的操作符。
我们来看代码:

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

结果为10
继续看接下来的代码(计算数组的元素个数):

#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++)//这里写10{arr[i] = i;}//输出数组的内容for(i=0; i<10; ++i){printf("%d ", arr[i]);}return 0;
}

总结:

  1. 数组是使用下标来访问的,下标是从0开始。
  2. 数组的大小可以通过计算得到。

int arr[10];
int sz = sizeof(arr) / sizeof(arr[0]);

1.4 一维数组在内存中的存储

接下来我们探讨数组在内存中的存储。
看代码:

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

*(p + 1)指的是将p + 1的内存解引用,取p + 1内存里面的元素个数

int main()
{int arr[10] = { 0 };int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);int* p = &arr[0];for (i = 0; i < sz; ++i){printf("%p = %p\n",p+i, &arr[i]);}return 0;
}

代码结果
内存连续存放

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

2. 二维数组的创建和初始化

2.1 二维数组的创建

数组创建
int arr[3][4];
char arr[3][5];
double arr[2][4];

2.2 二维数组的初始化

数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};
二维数组如果有初始化,行可以省略,列不能省略。

2.3 二维数组的使用

二维数组的使用也是通过下标的方式。
看代码:

#include <stdio.h>
int main()
{//int arr1[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};//int arr1[][4] = { {1,2},{3,4},{5,6} };//二维数组如果初始化,行是可以省略的,但是列不能//char arr2[5][6];////1  2  3  4 //5  6  7  8//9 10 11 12//int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//printf("%d\n", arr1[1][2]);int i = 0;for (i = 0; i < 3; i++)//0 1 2{int j = 0;for (j = 0; j < 4; j++){printf("%-2d ", arr1[i][j]);}printf("\n");}return 0;
}

注意:%2d为右对齐,%-2d为左对齐。

2.4 二维数组在内存中的存储

像一维数组一样,这里我们尝试打印二维数组的每个元素。
看代码:

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

结果如下
在这里插入图片描述
图片模拟形成过程
在这里插入图片描述

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;
}

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

4. 数组作为函数参数

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

4.1 冒泡排序函数的错误设计

#include <stdio.h>
void bubble_sort(int arr[])
{int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//冒泡排序的趟数for (i = 0; i < sz - 1; i++){//一趟冒泡排序的过程int j = 0;for (j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}
int main()
{int arr[] = { 3,1,5,9,2,4,7,6,8,0 };//排序 - 升序//冒泡排序bubble_sort(arr);//arr是数组首元素的地址int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

出问题,那我们找一下问题,调试之后可以看到 bubble_sort 函数内部的 sz ,是1。
难道数组作为函数参数的时候,不是把整个数组的传递过去?

4.2 数组名是什么?

#include <stdio.h>
int main()
{
int arr[10] = {1,23,4,5};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%d\n", *arr);
//输出结果
return 0;
}
//数组的地址加1会跳过整个数组。
//数组首元素地址加1只会跳过一个元素

结论:

数组名是数组首元素的地址
但是有2个例外:
sizeof(数组名),数组名如果单独放在sizeof内部,这里的数组名表示整个数组,计算的是整个数组的大小。
&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
除此之外,遇到的所有的数组名都输数组首元素的地址。
数组的地址加1会跳过整个数组。
数组首元素地址加1只会跳过一个元素。

int main()
{int arr[10] = { 0 };printf("%p\n", arr);printf("%p\n", arr+1);printf("%p\n", &arr[0]);printf("%p\n", &arr[0]+1);printf("%p\n", &arr);printf("%p\n", &arr+1);//printf("%d\n", sizeof(arr));//40return 0;
}

4.3 冒泡排序函数的正确设计

当数组传参的时候,实际上只是把数组的首元素的地址传递过去了。
所以即使在函数参数部分写成数组的形式: int arr[] 表示的依然是一个指针: int *arr 。
那么,函数内部的 sizeof(arr) 结果是4。

#include <stdio.h>
void bubble_sort(int *arr, int sz)
{int i = 0;//冒泡排序的趟数for (i = 0; i < sz - 1; i++){//一趟冒泡排序的过程int j = 0;for (j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}
int main()
{int arr[] = { 3,1,5,9,2,4,7,6,8,0 };//排序 - 升序//冒泡排序int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);//arr是数组首元素的地址int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

如果这份博客对大家有帮助,希望各位给恒川一个免费的点赞作为鼓励,并评论收藏一下,谢谢大家!!!
制作不易,如果大家有什么疑问或给恒川的意见,欢迎评论区留言。
下期内容将会带来扫雷,三子棋等有趣游戏!

相关文章:

C语言数组【详解】

数组1. 一维数组的创建和初始化1.1 数组的创建1.2 数组的初始化1.3 一维数组的使用1.4 一维数组在内存中的存储2. 二维数组的创建和初始化2.1 二维数组的创建2.2 二维数组的初始化2.3 二维数组的使用2.4 二维数组在内存中的存储3. 数组越界4. 数组作为函数参数4.1 冒泡排序函数…...

并行与体系结构会议

A类会议 USENIX ATC 2022: USENIX Annual Technical Conference&#xff08;录用率21%&#xff09; CCF a, CORE a, QUALIS a1 会议截稿日期&#xff1a;2022-01-06 会议通知日期&#xff1a;2022-04-29 会议日期&#xff1a;2022-07-11 会议地点&#xff1a;Carlsbad, Califo…...

【巨人的肩膀】JAVA面试总结(三)

1、&#x1f4aa; 目录1、&#x1f4aa;1、说说List, Set, Queue, Map 四者的区别1.1、List1.2、Set1.3、Map2、如何选用集合4、线程安全的集合有哪些&#xff1f;线程不安全的呢&#xff1f;3、为什么需要使用集合4、comparable和Comparator的区别5、无序性和不可重复性的含义…...

嵌入式 STM32 SHT31温湿度传感器

目录 简介 1、原理图 2、时序说明 数据传输 起始信号 结束信号 3、SHT31读写数据 SHT31指令集 读数据 温湿度转换 4、温湿度转换应用 sht3x初始化 读取温湿度 简介 什么是SHT31&#xff1f; 一主机多从机--通过寻址的方式--每个从机都有唯一的地址&…...

哪款蓝牙耳机打电话好用?打电话音质好的蓝牙耳机

现在几乎是人人离不开耳机的时代。在快节奏的生活和充满嘈杂声音的世界中&#xff0c;戴着耳机听歌&#xff0c;是每个人生活中最不可或缺的一段自由、放松的时光&#xff0c;下面小编就来分享几款通话音质好的蓝牙耳机。 一、南卡小音舱蓝牙耳机 动圈单元&#xff1a;13.3mm…...

【C++】-- 内存泄漏

目录 内存泄漏 内存泄漏分类 如何检测内存泄漏 如何避免内存泄漏 内存泄漏 #问&#xff1a;什么是内存泄漏&#xff1f;内存泄漏&#xff1a;指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失&#xff0c;而是应用程序分配某…...

C++ STL学习之【string类的模拟实现】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 The key is to keep company only with people who uplift you, whose presence calls forth your best. 关键是只与那些提升你的人在一起&#xff0c…...

Selenium基于POM的自动化测试实践

什么是Page Object模式 Page Object 见名知意&#xff0c;就是页面对象&#xff0c;并将页面元素定位方法和元素操作进行分离。在实际自动化测试实战过程中&#xff0c;我们一般对脚本的实现分为三层&#xff1a; (1)对象层&#xff1a; 用于存放页面元素定位和控件操作 (2)逻…...

记录每日LeetCode 2373.矩阵中的局部最大值 Java实现

题目描述&#xff1a; 给你一个大小为 n x n 的整数矩阵 grid 。 生成一个大小为 (n - 2) x (n - 2) 的整数矩阵 maxLocal &#xff0c;并满足&#xff1a; maxLocal[i][j] 等于 grid 中以 i 1 行和 j 1 列为中心的 3 x 3 矩阵中的 最大值 。 换句话说&#xff0c;我们希…...

QT中级(6)基于QT的文件传输工具(2)

QT中级&#xff08;6&#xff09;基于QT的文件传输工具&#xff08;2&#xff09;本文实现第一步1 新增功能2 运行效果3 实现思路4 源代码实现这个文件传输工具大概需要那几步&#xff1f;实现多线程对文件的读写实现TCP客户端和服务端实现网络传输 书接上回&#xff1a;QT中级…...

【Linux】工具(3)——gcc/g++

咱们继续进阶&#xff0c;接下来进入到Linux工具中gcc和g的学习在本章博客正式开始介绍之前&#xff0c;我们先要弄清楚程序是怎么翻译的&#xff1a;C语言程序环境一、什么是gcc/g&#x1f4cc;gcc是一个c编译器&#xff0c; g是c编译器。我们根据代码的后缀名来判断用哪个编译…...

Android文件选择器

使用方法:在里层的build.grade的dependency里面加入: implementation com.leon:lfilepickerlibrary:1.8.0 引用https://github.com/leonHua/LFilePicker/blob/master/README_CH.md#lfilepicker LFilePicker 说明:如果发现应用名称被修改,可以参考issues#26 查看解决方案,或…...

《MySql学习》 Select 查询语句慢的非性能原因

一.查询被阻塞 A会话执行 查询操作&#xff0c;长时间没有返回信息,此时我们就可以去排查一下是否是被阻塞了 select * from words 被阻塞的原因有很多&#xff0c;首先列举第一种情况 1.等MDL锁 当我们执行DDL语句时&#xff0c;会自动给表加上MDL写锁。当执行DML和DQL时&…...

Vue组件间通信方式超详细(父传子、父传后代、子传父、后代传父、兄弟组件传值)

一、父传子、父传后代 方式一&#xff1a;子通过props来接收 父组件&#xff1a;父组件引入子组件时&#xff0c;通过<child :parentValue "parentValue"></child>子组件传值。 备注&#xff1a;这种方式父传值很方便&#xff0c;但是传递给后代组件不…...

【ES】Elasticsearch-深入理解索引原理

文章目录Elasticsearch-深入理解索引原理读操作更新操作SHARD不变性动态更新索引删除和更新实时索引更新持久化Segment合并近实时搜索&#xff0c;段数据刷新&#xff0c;数据可见性更新和事务日志更新索引并且将改动提交修改Searcher对象默认的更新时间Elasticsearch-深入理解…...

pdf压缩文件大小的方法是什么?word文件怎么批量转换成pdf格式?

大家在存储文件时&#xff0c;通常会遇到一些较大的文件&#xff0c;这时需要对其进行压缩处理。下面介绍一下如何压缩PDF文件大小以及批量转换Word文件为PDF格式。pdf压缩文件大小的方法是什么?1.打开小圆象PDF转换器&#xff0c;选择“PDF压缩”功能。2.在“PDF压缩”界面中…...

论文阅读——FECANet:应用特征增强的上下文感知小样本语义分割网络

代码&#xff1a;NUST-Machine-Intelligence-Laboratory/FECANET (github.com) 文章地址&#xff1a;地址 文章名称&#xff1a;FECANet: Boosting Few-Shot Semantic Segmentation with Feature-Enhanced Context-Aware Network 摘要 Few-shot semantic segmentation 是学习…...

数组模拟常见数据结构

我们来学习一下用数组模拟常见的数据结构&#xff1a;单链表&#xff0c;双链表&#xff0c;栈&#xff0c;队列。用数组模拟这些常见的数据结构&#xff0c;需要我们对这些数据结构有一定的了解哈。单链表请参考&#xff1a;http://t.csdn.cn/SUv8F 用数组模拟实现比STL要快&a…...

ADC0832的AD模数转换原理及编程

✅作者简介&#xff1a;嵌入式领域优质创作者&#xff0c;博客专家 ✨个人主页&#xff1a;咸鱼弟 &#x1f525;系列专栏&#xff1a;单片机设计专栏 &#x1f4c3;推荐一款求职面试、刷题神器&#x1f449;注册免费刷题 目录 一、描述 二、模数转换原理&#xff1a; 三、…...

【工具插件类教学】UnityPackageManager私人定制资源工具包

目录 一.UnityPackageManager的介绍 二.package包命名 三.包的布局 四.生成清单文件 五.制作package内功能 六.为您的软件包撰写文档 1.信息的结构 2.文档格式 七.提交上传云端仓库 1.生成程序集文件 2.上传至云端仓库 八.下载使用package包 1.获取包的云端路径 …...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

6.9-QT模拟计算器

源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...

跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践

在电商行业蓬勃发展的当下&#xff0c;多平台运营已成为众多商家的必然选择。然而&#xff0c;不同电商平台在商品数据接口方面存在差异&#xff0c;导致商家在跨平台运营时面临诸多挑战&#xff0c;如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...

Spring是如何实现无代理对象的循环依赖

无代理对象的循环依赖 什么是循环依赖解决方案实现方式测试验证 引入代理对象的影响创建代理对象问题分析 源码见&#xff1a;mini-spring 什么是循环依赖 循环依赖是指在对象创建过程中&#xff0c;两个或多个对象相互依赖&#xff0c;导致创建过程陷入死循环。以下通过一个简…...