【C语言 | 数组】C语言数组详解(经典,超详细)

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍C语言的数组🍭
😎金句分享😎:🍭🍭

本文未经允许,不得转发!!!

目录

  • 🎄一、了解数组,清楚这五个方面
    • ✨1.1 数组所在的内存地址
    • ✨1.2 数组的内容
    • ✨1.3 数组的类型
    • ✨1.4 数组元素的类型
    • ✨1.5 数组元素的个数
  • 🎄二、数组的几个地址—— a、&a、&a[0]
  • 🎄三、不指定数组长度——int a[]={1,2};
  • 🎄四、数组初始化
  • 🎄五、字符串
  • 🎄六、总结


在这里插入图片描述

🎄一、了解数组,清楚这五个方面

如果定义一个基本数据类型变量,我们可以了解到这三个方面的内容:1、变量所在的内存地址; 2、变量的值; 3、变量的类型;

例如:从语句 int i = 1; ,我们可以知道:

  • 1、编译器分配一块4个字节(sizeof(int))的内存,地址是&i
  • 2、这块内存里面存放了值为4的内容;
  • 3、这个变量是 int 类型的。

如果定义的是数组,则我们需要清楚四个方面的内容:

  • 1、数组所在的内存地址;
  • 2、数组的内容;
  • 3、数组的类型;
  • 4、数组的元素类型;
  • 5、数组的元素个数;

✨1.1 数组所在的内存地址

定义了一个任何类型变量,编译器都会为其分配一块内存来存放该变量,起始地址就是 &变量名 ,大小就是该变量的类型的大小。

所以数组也是如此,定义一个数组后,编译器会为该数组分配一块内存。内存大小,就是数组类型的大小。例如:语句int a[5];,编译器会分配一块内存,起始地址可以通过&a来获取,内存大小是20个字节(sizeof(int [5]))。

数组所在的内存地址(数组的地址),就是 &数组名 的值。


✨1.2 数组的内容

数组的内容是指定义数组时,分配的那块内存里存放的东西,与数组元素类型数组元素个数 有关。

数组的内容就是由若干个 固定大小 的内存块,线性排列组成的一个内存块。这里的若干个就是数组元素个数固定大小就是sizeof(数组元素类型)


✨1.3 数组的类型

针对基本数据类型变量 或 指针变量,大部分人都可以轻易指出该变量的类型是什么。

看例子1.3.1:

// array_type.c
char c;		// char 类型
int i;		// int 类型
char *pc;	// char* 类型
int *pi;	// int* 类型

那么,数组的类型是什么?好像以前都没听过这个词汇!!!

仔细观察上面例子,变量的类型都是在定义语句中,把变量名去掉,就得到该变量的类型。同样地,在数组定义语句中把数组名去掉就是数组的类型。

看例子1.3.2:

#include <stdio.h>int main()
{char ca[10];    // 数组类型是 char [10]int ia[5];      // 数组类型是 int [5]char *pca[8];   // 数组类型是 char *[8]int  *aapi[4][5];//数组类型是 int *[4][5]int  (*apai[4])[5];//数组类型是 int (*[4])[5])printf(" sizeof(aapi)=%lu, %lu\n", sizeof(aapi), sizeof(int *[4][5]));printf(" sizeof(apai)=%lu, %lu\n", sizeof(apai), sizeof(int (*[4])[5]));return 0;
}

从这个例子,可以轻易指出数组的类型在数组定义语句中,把数组名去掉,剩下的就是数组的类型。

但是,在例子中,aapiapai 变量的类型可能又把一部分人的CPU干烧了。
这里需要使用一个右左法则来阅读复杂类型:

右左法则

  • 1、从变量名(没变量名的,从最里层的圆括号)开始,先看右边,再看左边;
  • 2、如果右边是() 则是函数,如果是 [] 则是数组。
  • 3、如果遇到[],后面还是[],就先看完右边的[],再看左边。
    例如:int *pi[4][5];,p先跟[4][5]结合,再跟*结合。

变量aapi,先跟右边[4]结合,说明是一个有4个元素数组;再跟[5]结合,说明数组的每个元素都是带有5个元素数组;再跟左边*结合,表示第二维数组的5个元素都是指针;再跟左边int结合,表示指针指向int类型数据。

变量apai,先跟右边[4]结合,说明是一个有4个元素数组;因为()改变优先级,再跟*结合,说明数组的每个元素都是指针;再跟右边[5]结合,表示每个指针指向带有5个元素的数组;再跟左边int结合,表示这些数组都是int类型的。


✨1.4 数组元素的类型

在数组定义语句中,把数组名和后面的[]去掉,剩下的就是数组元素的类型。

看例子1.4.1:

// array_unit_type.c
#include <stdio.h>int main()
{char ca[10];    // 数组元素类型是 char int ia[5];      // 数组元素类型是 int char *pca[8];   // 数组元素类型是 char *int  *aapi[4][5];//数组元素类型是 int *[5]int  (*apai[4])[5];//数组元素类型是 int (*)[5])printf(" sizeof(aapi[0])=%lu, %lu\n", sizeof(aapi[0]), sizeof(int *[5]));printf(" sizeof(apai[0])=%lu, %lu\n", sizeof(apai[0]), sizeof(int (*)[5]));return 0;
}

例子中,前三个类型都比较容易看明白,int *[5]int (*)[5] 分别是什么类型?
int *[5] 类型表示一个数组,每个数组元素都是int *类型。
int (*)[5]类型表示一个指向包含5个int型元素的数组的指针 。

✨1.5 数组元素的个数

C语言中,在定义数组时,都需要明确的给出数组元素个数。

在数组定义语句中,数组名后面的[]中的数字,就是数组元素的个数。

int a[5];为例子,数组个数可以用表达式:sizeof(a) / sizeof(a[0]) 来获得。

在这里插入图片描述

在这里插入图片描述

🎄二、数组的几个地址—— a、&a、&a[0]

当我们定义一个数组 a 时,编译器根据指定的元素个数和元素的类型分配确定大小(元素类型大小*元素个数)的一块内存,并把这块内存的名字命名为 a。名字 a 一旦与这块内存匹配就不能被改变。

a[0]、a[1]等为 a 的元素,但并非元素的名字。数组的每一个元素都是没有名字的。

  • 数组名a:数组名a作为地址使用时,表示数组首个元素的地址(指针),那它所指向的类型就是数组元素类型,加减一个整数就相当于加减(整数*sizeof(元素类型))
    数组名a可以看成一个指针常量,它的值不能被修改,不能单独作为左值使用。
  • &a&a表示对编译器分配好内存的变量a取地址,得到的是整个数组的地址(指针),其所指向的类型是数组的类型,加减一个整数就相当于加减(整数*sizeof(数组的类型))
  • &a[0]a[0]是数组的首个元素,&a[0]是对数组首个元素取地址,得到的是数组首个元素的地址(指针),那它所指向的类型就是数组元素类型,加减一个整数就相当于加减(整数*sizeof(元素类型))

看例子2.1:

// array_addr.c
#include <stdio.h>int main()
{int a[5];// 数组类型:int [5] ; 数组元素类型:intprintf("a=%p a+1=%p %lx\n",a, a+1,  (unsigned long)a+sizeof(int));printf("&a=%p &a+1=%p %lx\n",&a, &a+1,  (unsigned long)&a+sizeof(int [5]));printf("&a[0]=%p &a[0]+1=%p %lx\n",&a[0], &a[0]+1,  (unsigned long)&a[0]+sizeof(int));printf("a=%lu &a=%lu &a[0]=%lu\n",sizeof(a), sizeof(&a), sizeof(&a[0]));return 0;
}

打印结果如下:
在这里插入图片描述

从结果看,可以得出结论:

  • a、&a、&a[0]作为地址(指针)使用时,三个值都是相等的;
  • a、&a、&a[0]的指针类型不一样,&a的指针类型是数组的类型,a、&a[0]的指针类型是数组元素类型,最后进行指针运算时,a、&a[0]的结果是一样的,与&a存在差别;
  • a、&a、&a[0]进行sizeof计算时,sizeof(a)是这个数组大小,其余两个是指针的大小(32位系统为4,64位系统为8)。

在这里插入图片描述

🎄三、不指定数组长度——int a[]={1,2};

在C语言中,可以使用不指定数组长度的方式来定义和初始化数组。这种情况下,编译器会根据提供的初始化值自动推断数组的长度。

例如,代码int a[]={1,2};定义了一个整型数组a,并用初始值1和2进行了初始化。由于未指定数组长度,编译器会根据提供的初始化值计算数组的大小。

在这个例子中,由于提供了两个初始化值,编译器会推断数组长度为2,因此数组a将具有两个元素:a[0]和a[1]。其值分别为:

a[0] = 1
a[1] = 2

通过这种方式,可以方便地定义和初始化具有不同长度的数组,而无需显式指定数组的长度。但是请注意,这种隐式推断数组长度的方式只适用于在声明时进行初始化的静态和自动(非堆)数组。对于动态分配的数组,仍然需要显式指定数组的长度。

总结起来,使用不指定数组长度的方式定义和初始化数组是C语言中的一种常见用法,编译器会根据提供的初始化值来推断数组的长度。
在这里插入图片描述

🎄四、数组初始化

在C语言中,主要有3种常见的方式可以初始化数组。下面列举了其中的几种方式,并提供了相应的示例:

  • 1、在定义数组时,给各个元素初始化。
    int a[5] = {1, 2, 3, 4, 5};
    
  • 2、部分初始化:只为数组的一部分元素提供初始值,剩余元素会被设置为默认值(0)
    int a[5] = {1, 2}; // a[0]和a[1]被初始化为1和2,a[2]、a[3]和a[4]被初始化为0
    
  • 3、不指定数组长度的方式定义和初始化数组。这是C语言中的一种常见用法,编译器会根据提供的初始化值来推断数组的长度。
    int a[]={1,2}; // 初始化结束后,数组a的长度为2
    char str[] = "Hello"; // 字符数组str会被初始化为包含"Hello"字符串的字符序列
    

这些是C语言中常见的数组初始化方式,你可以根据自己的需求选择适合的方式来初始化数组。
看例子4.1:

// array_init.c
#include <stdio.h>int main()
{int i=0;printf("no init:\n");int a[5];for(i=0; i<(sizeof(a)/sizeof(a[0])); i++){printf("%d, ",a[i]);// 没初始化,打印随机值}printf("\n\n");printf("init1: init all unit\n");int a1[5] = {1,2,3,4,5};for(i=0; i<(sizeof(a1)/sizeof(a1[0])); i++){printf("%d, ",a1[i]);}printf("\n\n");printf("init2: init first unit\n");int a2[5] = {5};for(i=0; i<(sizeof(a2)/sizeof(a2[0])); i++){printf("%d, ",a2[i]);}printf("\n\n");printf("init3: Do not specify length\n");int a3[] = {1,2,3,4,5};for(i=0; i<(sizeof(a3)/sizeof(a3[0])); i++){printf("%d, ",a3[i]);}printf("\n\n");printf("init4: Specify some unit\n");int a4[5] = {[1]=2, [3]=4};for(i=0; i<(sizeof(a4)/sizeof(a4[0])); i++){printf("%d, ",a4[i]);}printf("\n\n");printf("init5: Do not specify length, and specify the unit\n");int a5[] = {[1]=2, [3]=4};for(i=0; i<(sizeof(a5)/sizeof(a5[0])); i++){printf("%d, ",a5[i]);}printf("\n");return 0;
}

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

在这里插入图片描述

🎄五、字符串

C语言中的字符串,本质为字符数组,编译器自动在结尾加上 ‘\0’ 字符。

字符串字面值可以用来初始化字符数组:char str[]="abc";

字符串字面值存储于程序的全局只读存诸区,内容不可以修改,地址可以看出常量指针,指针类型是const char * const

字符串字面值的长度可以用strlen函数来获取。

// array_str.c
#include <stdio.h>
#include <string.h>int main()
{// 1、字符串字面值的地址、空间大小、字符串长度printf("str_addr=%p str_size=%lu str_len%lu\n", (char*)"str", sizeof("str"), strlen("str"));// 2、字符串字面值给字符数组初始化unsigned char str[100] = "12345";// 3、字符串字面值是 `const char* const` 指针printf("str_1=[%c] str_end=[%c]\n", *("str"+1), *("str"+strlen("str")));return 0;
}

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

在这里插入图片描述

🎄六、总结

本文详细地介绍C语言的数组,数组本质上是一段连续的内存空间,了解数组5个重要内容:数组所在的内存地址、数组的内容、数组的类型、数组元素的类型、数组元素的个数;然后介绍数组的几个地址—— a、&a、&a[0];数组的初始化、字符串等。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

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

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

相关文章

Unity开发之C#基础-异常处理(Try Catch)

前言 其实本来这章应该将栈和队列的 但是后来想想 栈和队列在实际应用很少跟多的是大家了解一下栈和队列的基本常识比如先进先出的是谁后进先出的是谁这种 csdn有很多介绍栈和队列的文章 我觉得都比我理解深刻所以大家可以去搜索参照一下 今天我们继续往下讲解 如何自己主动的…

如何从Android手机恢复已删除的联系人

联系人应该是最重要的信息之一。 如果您不小心从Android手机中删除了联系人&#xff0c;该怎么办&#xff1f; 如果不容易找回丢失的联系人&#xff0c;您可以使用奇客数据恢复安卓版。 从Android的手机中恢复已删除的联系人 只需删除Android联系人&#xff0c;然后您就可以通…

ubuntu中使用 vscode 连接docker开发环境

文章目录 ubuntu中使用 vscode 连接docker开发环境步骤一&#xff1a;安装 Remote Development 插件步骤二&#xff1a;连接远程环境步骤三&#xff1a;开发 问题解决参考连接 ubuntu中使用 vscode 连接docker开发环境 Remote Development 是一个 Visual Studio Code 插件&…

WPF小知识

在编写WPF程序遇到一些小问题&#xff0c;所以记录起来&#xff0c;查其他方便。 Label自动换行 网上搜的都不能自动换行&#xff0c;发现使用Run 就可以。在脚本中直接调用labTip.Text进行赋值就可以了。 <Label Foreground"#FF9E9E9E" FontSize"16"…

Google codelab WebGPU入门教程源码<4> - 使用Uniform类型对象给着色器传数据(源码)

对应的教程文章: https://codelabs.developers.google.com/your-first-webgpu-app?hlzh-cn#5 对应的源码执行效果: 对应的教程源码: 此处源码和教程本身提供的部分代码可能存在一点差异。 class Color4 {r: number;g: number;b: number;a: number;constructor(pr 1.0, …

【hive-解决】HiveAccessControlException Permission denied: CREATEFUNCTION

文章目录 一.任务描述二. 解决 一.任务描述 Error while compiling statement: FAILED: HiveAccessControlException Permission denied: Principal [nameroot, typeUSER] does not have following privileges for operation CREATEFUNCTION [ADMIN PRIVILEGE on INPUT, ADMIN…

华为 Mate 60 Pro 拆解:陆制零件比率上升至47% | 百能云芯

近日&#xff0c;日经新闻联合研究公司Fomalhaut Techno Solutions对华为 Mate 60 Pro 进行了拆解&#xff0c;揭示了这款于8月发布的新型智能手机的成本结构。拆解结果显示&#xff0c;该手机的国产零部件比例达到了47%&#xff0c;相较于三年前的 Mate 40 Pro&#xff0c;提高…

自动驾驶汽车:人工智能最具挑战性的任务

据说&#xff0c;自动驾驶汽车是汽车行业梦寐以求的状态&#xff0c;将彻底改变交通运输业。就在几年前&#xff0c;对自动驾驶汽车的炒作风靡一时&#xff0c;那么到底发生了什么呢&#xff1f;这么多公司吹嘘到2021年我们将迎来的无人驾驶汽车革命在何处&#xff1f;事实证明…

(论文阅读31/100)Stacked hourglass networks for human pose estimation

31.文献阅读笔记 简介 题目 Stacked hourglass networks for human pose estimation 作者 Alejandro Newell, Kaiyu Yang, and Jia Deng, ECCV, 2016. 原文链接 https://arxiv.org/pdf/1603.06937.pdf 关键词 Human Pose Estimation 研究问题 CNN运用于Human Pose E…

基于 selenium 实现网站图片采集

写在前面 有小伙伴选题&#xff0c;简单整理理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所有其它的路都是不完整的&#xff0c;是人的逃避方式&#xff0c;是对…

RabbitMQ之发布确认高级

文章目录 前言一、发布确认 整合springboot1、确认机制方案2、代码架构图3、配置文件4、添加配置类5、消息生产者6、回调接口7、消息消费者8、结果分析 二、回退消息1、Mandatory 参数2、消息生产者代码3、回调接口4、结果分析 三、备份交换机1、代码架构图2、修改配置类3、报警…

jQuery【jQuery树遍历、jQuery动画(一)、jQuery动画(二)】(四)-全面详解(学习总结---从入门到深化)

目录 jQuery树遍历 jQuery动画(一) jQuery动画(二) jQuery树遍历 1、 .children() 获得子元素&#xff0c;可以传递一个选择器参数 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-…

【152.乘积最大子数组】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 class Solution { public:int maxProduct(vector<int>& nums) {int nnums.size();vector<int> f(n);vector<int> g(n);f[0]g[0]nums[0];int retnums[0];for(int i1;…

html书本翻页效果,浪漫表白日记本(附源码)

文章目录 1.设计来源1.1 书本正面1.2 界面1-21.3 界面3-41.4 界面5-61.5 界面7-81.6 界面9-101.7 界面11-121.8 书本结尾 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/1…

JS进阶——构造函数数据常用函数

1、深入对象 1.1 创建对象三种方式 1.1.1 利用对象字面量创建对象 1.1.2 利用new Object创建对象 1.1.3 利用构造函数创建对象 1.2 构造函数 构造函数&#xff1a;是一种特殊的函数&#xff0c;主要用来初始化对象 使用场景&#xff1a;常规的{...}语法允许创建一个对象。…

创邻科技亮相ISWC 2023,国际舞台见证知识图谱领域研究突破

近日&#xff0c;第22届国际语义网大会 ISWC 2023 在雅典希腊召开&#xff0c;通过线上线下的形式&#xff0c;聚集了全球的顶级研究人员、从业人员和行业专家&#xff0c;讨论、发展和塑造语义网和知识图谱技术的未来。创邻科技CEO张晨博士作为知识图谱行业专家受邀参会&#…

熟悉 Unity HDRP设置以提高性能

HDRP Version 10 了解如何利用高清晰度渲染管道(HDRP)设置&#xff0c;以最大限度地提高性能&#xff0c;并一次实现强大的图形。 随着Unity 2020 LTS及以后的HDRP版本10的发布&#xff0c;HDRP包继续优先考虑其用户友好的界面&#xff0c;灵活的功能&#xff0c;稳定性和总体…

2023年软件安装管家目录最新

软件目录 ①【电脑办公】电脑系统&#xff08;直接安装&#xff09;Win7Win8Win10OfficeOffice激活office2003office2007office2010office2013office2016office2019office365office2021wps2021Projectproject2007project2010project2016project2019project2013project2021Visio…

机器学习中的独立和同分布 (IID):假设和影响

一、介绍 在机器学习中&#xff0c;独立和同分布 &#xff08;IID&#xff09; 的概念在数据分析、模型训练和评估的各个方面都起着至关重要的作用。IID 假设是确保许多机器学习算法和统计技术的可靠性和有效性的基础。本文探讨了 IID 在机器学习中的重要性、其假设及其对模型开…

leetcode刷题日记:141. Linked List Cycle(环形链表)

这一题是给我们一个链表让我们判断这是否是一个环形链表&#xff0c;我们知道如果一个链表中有环的话这一个链表是没有办法访问到尾的&#xff0c; 假若有如图所示的带环链表&#xff1a; 我们从图示中很容易看出来这一个链表在访问的时候会在里面转圈&#xff0c;我们再来看看…