C语言复习第4章 数组

news2024/11/30 14:38:31

目录

  • 一、一维数组的创建和初始化
    • 1.1数组的创建
    • 1.2 变长数组
    • 1.3 数组的初始化
    • 1.4 全局数组默认初始化为0
    • 1.5 区分两种字符数组
    • 1.6 用sizeof计算数组元素个数
    • 1.7 如何访问数组元素
    • 1.8 一维数组在内存中的存储(连续存储)
    • 1.9 访问数组元素的另一种方式:指针变量
    • 1.10 数组越界是运行时错误
  • 二、二维数组的创建和初始化
    • 2.1 二维数组的创建
    • 2.2 二维数组的初始化
    • 2.3 行可以省略 列不可以省略
    • 2.4 二维数组在内存中的存储(连续存储)
    • 2.5 二维数组的遍历方式
    • 2.6 arr[行号]可以理解为:该行一维数组的`数组名`
  • 三、数组名
    • 3.1 数组名是首元素地址
    • 3.2 数组名代表`整个数组`的两个例外:sizeof和&
    • 3.3 sizeof(arr)和sizeof(arr+0)的区别
    • 3.4 arr和&arr类型的区别
    • 3.5 &arr 和*(&arr)-数组指针解引用得到数组名
    • 3.6 **(&arr) 解引用两次是什么?
    • 3.7 sizeof(*&arr) 和 sizeof(arr)
    • 3.8 再理解一下 什么叫单独放在&或sizeof(含总结)
    • 3.9 sizeof(数组名)和strlen(数组名)
  • 四、数组(名)作为函数参数
    • 4.1 数组(名)作为函数参数 本质传的是什么?
    • 4.2 冒泡排序函数的错误设计
    • 4.3 理解形参int arr[ ] arr[j] &arr[j]的本质
    • 4.4 思考:为什么数组传参 本质要传首元素的地址?
    • 4.5 二维数组传参
  • 五、其他
    • 怎么看数组的类型是什么
    • 用整数初始化字符数组会怎么样
    • 一个例题

一、一维数组的创建和初始化

1.1数组的创建

数组的创建方式:type_t arr_name [const_n]
type_t 是指数组的元素类型
const_n 是一个常量表达式 用来指定数组的大 比如int arr[5+6]

1.2 变长数组

int arr[5];int arr[5+6]都可以
可不可以是int arr[n]呢?
在这里插入图片描述

1.3 数组的初始化

1.不完全初始化 会根据指定的元素个数 把剩余部分初始化为0
2.char数组不完全初始化 剩余部分默认初始化为’\0’ '\0'的码值是0
3.如果不写元素个数 那就必须初始化 编译器会根据初始化的内容确定元素个数 在这里插入图片描述

所以下图的两个数组是不一样的
一个是arr[3] = {1,2,3}
一个是arr[10] = {1,2,3,0,0,0,0,0,0,0}
在这里插入图片描述

  • 注意字符串自带’\0’
    在这里插入图片描述

  • 一些离谱的写法:
    在这里插入图片描述

1.4 全局数组默认初始化为0

  • 在VS2022里 全局数组不初始化 默认都是0
  • 但是局部数组不初始化 整形数组是cccccccc char数组是问号
    在这里插入图片描述
    在这里插入图片描述

1.5 区分两种字符数组

  • "abc"自带’\0’
  • %s是打印到第一个’\0’才停止的
    在这里插入图片描述

1.6 用sizeof计算数组元素个数

这里sizeof(arr[0]) 也可以写成sizeof(int)
但是前者更合逻辑(一个元素的大小)
在这里插入图片描述

1.7 如何访问数组元素

在这里插入图片描述

1.8 一维数组在内存中的存储(连续存储)

● 内存单元的大小为1字节 而int是4个字节(则每个元素占4个内存单元)
● 一维数组在内存中是 连续存储
随着数组下标增长 地址由低到高变化(从低地址用到高地址)
在这里插入图片描述

再结合之前画过的图 推测:
下标越高的元素 其实是越先入栈的 在这里插入图片描述
在这里插入图片描述

1.9 访问数组元素的另一种方式:指针变量

● 所以 给我数组的首元素地址 根据连续存储特点 我就能顺藤摸瓜依次找到整个数组
● p是个整型指针 +1就跳过一个整型
*(p+i) == arr[i]在这里插入图片描述
在这里插入图片描述

p+i == &arr[i]
在这里插入图片描述

1.10 数组越界是运行时错误

  • 数组的下规定是从0开始的 如果数组有n个元素 最后一个元素的下标就是n-1
  • 所以数组的下标如果小于0 或者大于n-1 就是数组越界访问了
  • C语言本身是不做数组下标的越界检查 编译器也不一定报错
  • 编译器不报错 并不意味着程序就是正确的 所以写代码时 做好越界的检查

打印随机值:
可能是没有初始化 也可能是数组越界访问
下图编译器虽然不报错 但是程序明显是错误的
在这里插入图片描述

假如这里给arr[i]赋值的话 就会报错在这里插入图片描述

二、二维数组的创建和初始化

2.1 二维数组的创建

在这里插入图片描述

2.2 二维数组的初始化

  • 不完全初始化 默认也是0和’\0’
    在这里插入图片描述
  • 可以帮一维数组的每个元素看做一维数组
    在这里插入图片描述

2.3 行可以省略 列不可以省略

如果下面这个不给行数3 定义成[ ][4] 它也是可以知道是1234 5678 9000的
因为反正知道一行要放几个元素(列数已知)
如果定义成[4][ ] 编译器就不知道怎么办 一上来要怎么放?
所以
列不可以省略
行可以通过每列放几个来确定 所以行可以省略(前提是 后面有具体的初始化内容了)
在这里插入图片描述

2.4 二维数组在内存中的存储(连续存储)

  • 二维数组在内存中 其实也是连续存放的
    在这里插入图片描述
    在这里插入图片描述

2.5 二维数组的遍历方式

其实也一维数组类似
方式1 利用行号和列号
方式2 利用其连续存放的特性 把下图的二维数组直接看作一个12个元素的一维数组
在这里插入图片描述

方式3 利用2.6的理解
2.6说了:arr[i]是第i行一维数组的数组名
arr是二维数组的数组名
数组名 单独 放在sizeof里 求的是整个数组的大小!
sizeof(arr[0][0])是一个元素的大小 等价于sizeof(int)
整个二维数组大小/每一行一维数组大小=sizeof(arr)/sizeof(arr[0])=行数
每一行一维数组大小/每个元素大小=sizeof(arr[0])/sizeof(arr[0][0])=列数
在这里插入图片描述

2.6 arr[行号]可以理解为:该行一维数组的数组名

arr[3][4] = {1,2,3,4,5,6,7,8,7,7,7,7}: 三个一维数组 每个一维数组四个元素
1 2 3 4—>数组名arr[0] arr[0][1]=2
5 6 7 8—>数组名arr[1]
7 7 7 7—>数组名arr[2]

二维数组是一维数组的数组
二维数组的每个元素(每一行) 可以看做一行一维数组 且每一行的数组名就是arr[行号]
如果把1 2 0 0看成一个一维数组的话
类比:
arr[i]:arr数组名 i下标 则arr[0][j]:arr[0]数组名 j下标
其中**arr[0]指的就是1 2 0 0这个一维数组的数组名**
以此类推 第二行的数组名就是arr[1]
在这里插入图片描述

三、数组名

3.1 数组名是首元素地址

在这里插入图片描述
在这里插入图片描述

3.2 数组名代表整个数组的两个例外:sizeof和&

● sizeof(单独放一个数组名) 则这里的数组名表示整个数组 计算的是整个数组的大小 单位是字节
● &单独跟一个数组名 则这里的数组名也表示整个数组 取出的是整个数组的地址
除了这两个例外 其他遇到的所有的数组名 都表示首元素地址

3.3 sizeof(arr)和sizeof(arr+0)的区别

sizeof(arr+0) 数组名不是单独放在sizeof里面 所以arr表示的还是首元素地址
arr如果参与运算 那肯定是个指针了 也就是看做首元素地址
在这里插入图片描述

3.4 arr和&arr类型的区别

在这里插入图片描述

arr和&arr虽然值相同 但类型是不一样的!!
一个是整型指针arr的类型是int*
一个是数组指针&arr的类型是int (*)[10]
这就是本质区别

在这里插入图片描述
在这里插入图片描述

p+1跳过几个字节 取决于指针的类型
int* p是整型指针 p+1跳过一个int大小的空间 4字节-类型是int*
char* p是字符指针 p+1跳过一个char大小的空间 1字节-类型是char*
&数组名是数组指针 p+1跳过一个数组大小的空间 元素个数*元素大小个字节-类型是int(*)[10]

在这里插入图片描述
在这里插入图片描述

3.5 &arr 和*(&arr)-数组指针解引用得到数组名

在这里插入图片描述

  • 所以都是求的整个数组的大小
    在这里插入图片描述

3.6 **(&arr) 解引用两次是什么?

再给p3解引用一次 发现就拿到了首元素1
但是p3可不是二级指针 传参的时候可不能写成二级指针
二级指针 一定是某个地址的地址
但是这里 p3是一整个数组的地址 p3应该是数组指针 而不是二级指针

在这里插入图片描述
其实我觉得 p3还真的可以理解成地址的地址
因为arr本身就是首元素地址 &arr不就是把地址的地址拿到了
(只能这么理解理解 但是这种说法是错的 前面已经提到过 &单独数组名拿的是整个数组的地址)
但是只能自己偷偷这么去理解 语法不是这样的

3.7 sizeof(*&arr) 和 sizeof(arr)

  • 求的都是整个数组的大小
    在这里插入图片描述

3.8 再理解一下 什么叫单独放在&或sizeof(含总结)

在这里插入图片描述

单独的情况下 arr[1]表示第二行数组的数组名
如果不是arr[1]"两个单独"的情况
那么数组名arr[1]表示首元素地址(就是第二行第一个元素的地址)

在这里插入图片描述

3.9 sizeof(数组名)和strlen(数组名)

  • strlen是专门针对字符串的函数
  • char arr[10]=“abc”;
    sizeof(arr)求出来就是10字节 放了什么内容没关系
    而strlen(arr)求到的就是\0之前的 求到3

四、数组(名)作为函数参数

4.1 数组(名)作为函数参数 本质传的是什么?

● arr不符合前面提到的"两个单独"这里arr就是首元素地址 本质上是指针
● 既然传过来的是地址 那么用指针接 才更规范
在这里插入图片描述
char ch[]本质就是char* ch
ch是指针变量 大小恒为8/4
在这里插入图片描述

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

下图是冒泡排序的一种经典错误
形参的int arr[] 本质上就是整型指针int* arr
既然本质是指针 sizeof计算的就是指针的大小 就是8/4字节 恒为2/1
在这里插入图片描述
在这里插入图片描述


● 把sz在main算好作为参数传进来 才是正确的做法
● 因为在main里 单独 把数组名arr给sizeof( ) 求的就是整个数组的大小
参考代码:

void Sort(int arr[],int sz)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{ 
		for (j = 0; j < sz - i - 1; j++)
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
	}
}

int main()
{
	int arr[] = { 10,9,8,7,6,100,5,4,3,2,1 };
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
		printf("%d ", arr[i]);
	printf("\n");

	Sort(arr, sizeof(arr) / sizeof(int));
	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
		printf("%d ", arr[i]);
		return 0;
}

其实主要看sizeof( )里放的本质是什么
如果在函数里再新定义一个数组 还是一样可以正确求出该数组的大小(字节)的
在这里插入图片描述

4.3 理解形参int arr[ ] arr[j] &arr[j]的本质

● 把本质是int* arr的东西写成int arr[ ] 主要是为了下面用下标访问的时候可能更好理解
● int arr[ ]从形式上好理解 但本质还是int arr*
arr[j]本质上是*(arr+j) 表示访问下标为j的元素
&arr[j]本质上是arr+j 表示下标为j的元素的地址
在这里插入图片描述

4.4 思考:为什么数组传参 本质要传首元素的地址?

思考为什么这么设计?
● 首先 前面提到 数组是连续存放在内存中的 所以只要知道起始地址 就可以顺藤摸瓜找到整个数组 只传一个首元素地址 可以"代表/找到整个数组"
● 其次 假设数组传参传的不是传址 而是一份数组的临时拷贝 那么假如我数组100000个元素? 浪费空间!!

4.5 二维数组传参

  • 请回看3.6
    在这里插入图片描述

五、其他

怎么看数组的类型是什么

int num = 10; 去掉变量名 剩下的就是类型
那么 int num[10] = {1,2,3}; 去掉num 剩下的int [10] 就是类型
即数组num的类型就是int [10] 而且这个10不能被省略
在这里插入图片描述

算大小也不会这么算 因为[ ]写几 还得自己去数一下
只能说 就借此理解一下 数组也是有类型的 就跟int a = 10的a一样
在这里插入图片描述

用整数初始化字符数组会怎么样

在这里插入图片描述

一个例题

&arr+ 跳过整个二维数组 指向最后一个越界的地方 然后用int*的权限-1 往后一个字节 再用int*的权限解引用 得到1
arr是首元素地址 也就是一个一维数组的地址 是一个数组指针 arr+1自然是有跳过一整个数组的权限 得到的就是第二个一维数组的地址 前面说 一个数组指针(指向数组的指针) 解引用之后得到了该数组的数组名 那么*(arr+1) 其实就是得到了第二个数组的数组名 也就是首元素5的地址 这个时候其实前面的强转都是多余的 然后同理解引用能得到6
● 那么其实可以推到:既然*(arr+1)表示第二个一维数组的数组名 *(arr+1)又等于arr[1] 那么其实可以理解为 对于二维数组arr来说 arr[i]得到的就是第i个元素(二维数组每个元素都是一个一维数组)的数组名
所以ptr2也可以理解成:ptr2 = (int*)arr[1] 也就是第二个一维数组的数组名 也就是元素值为5的地址 arr[1]的类型本来就是int*
在这里插入图片描述

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

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

相关文章

【AI绘画】Midjourney进阶:引导线构图详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;什么是构图为什么Midjourney要使用构图 &#x1f4af;引导线构图特点使用场景提示词书写技巧测试 &#x1f4af;小结 &#x1f4af;前言 【AI绘画】Midjourney进阶&a…

AnaTraf | TCP重传的工作原理与优化方法

目录 什么是TCP重传&#xff1f; TCP重传的常见触发原因 TCP重传对网络性能的影响 1. 高延迟与重传 2. 吞吐量的下降 如何优化和减少TCP重传 1. 优化网络设备配置 2. 优化网络链路 3. 网络带宽的合理规划 4. 部署CDN和缓存策略 结语 AnaTraf 网络性能监控系统NPM | …

网络最快的速度光速,因此‘‘光网络‘‘由此产生

世界上有一种最快的速度又是光,以前传统以太网络规划满足不了现在的需求。 一 有线网规划 二 无线网规划

如何用pyhton修改1000+图片的名字?

import os oldpath input("请输入文件路径&#xff08;在windows中复制那个图片文件夹的路径就可以):") #注意window系统中的路径用这个‘\分割&#xff0c;但是编程语言中一般都是正斜杠也就是’/‘ #这里写一个代码&#xff0c;将 \ > / path "" fo…

嵌入式职业规划

嵌入式职业规划 在嵌入式的软件开发中&#xff0c;可以分为&#xff1a; 嵌入式MCU软件开发工程师&#xff1b; 嵌入式Linux底层&#xff08;BSP&#xff09;软件开发工程师&#xff1b; 嵌入式Linux应用开发工程师&#xff1b; 嵌入式FPGA算法开发工程师 对于前两个阶段 …

H.266与H.265、AV1、H.264对比

好多开发者希望搞清楚H.266&#xff08;Versatile Video Coding&#xff0c;VVC&#xff09;、H.265&#xff08;High Efficiency Video Coding&#xff0c;HEVC&#xff09;、AV1、H.264&#xff08;Advanced Video Coding&#xff09;四者区别&#xff0c;本文从压缩效率、画…

代码随想录算法训练营第三十八天 | 62. 不同路径、63. 不同路径 II、343. 整数拆分、96.不同的二叉搜索树(343、96以后学)

1. 题目&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路…

提高EDM广告发送率和到达率_实用技巧揭秘

EDM广告提高发送率和到达率策略包括优化邮件服务器设置、制定邮件内容及设计策略、持续监测与测试。ZohoCampaigns通过可靠ESP、SPF和DKIM验证、维护IP声誉确保高发送率和到达率。 一、了解EDM的发送率和到达率概念 在深入研究提升策略之前&#xff0c;首先我们需要明确两个专…

2-126基于matlab希尔伯特黄变换(HHT)的图像三维重建

基于matlab希尔伯特黄变换&#xff08;HHT&#xff09;的图像三维重建&#xff0c;利用希尔伯特黄变换&#xff08;HHT&#xff09;的条纹图相位信息提取算法&#xff0c;对输入图片的变形条纹图相位信息进行提取&#xff0c;实现三维重建。程序已调通&#xff0c;可直接运行。…

Axure重要元件三——中继器时间排序

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 本节课&#xff1a;中继器数据时间排序 课程内容&#xff1a;数据的升序、降序、重置排序 应用场景&#xff1a;表单数据的排序 案例展示&#xff1a; 步骤一&#xff…

【数据分享】1901-2023年我国省市县三级逐月最低气温(免费获取/Shp/Excel格式)

之前我们分享过1901-2023年1km分辨率逐月最低气温栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff0c;该数据来源于国家青藏高原科学数据中心&#xff0c;很多小伙伴拿到数据后反馈栅格数据不太方便使用&#xff0c;问我们能不能把数据处理为更方便使用的Sh…

0基础学java之Day09(下午完整版)

六、数组 概念&#xff1a; 1.数组是引用数据类型 2.数组中的数据叫做元素 3.元素都有标号叫做索引/下标 4.下标从0开始 5.数组一旦初始化成功&#xff0c;长度不可变&#xff08;意味着数组没有添加和删除&#xff09; 6.数组中的元素在内存中是挨在一起的 声明&#xff1a; 数…

CTF(四)

导言&#xff1a; 本文主要讲述在CTF竞赛中&#xff0c;web类题目file_include。 靶场链接&#xff1a;攻防世界 (xctf.org.cn) 一&#xff0c;观察页面。 可以看到一段php代码。从则段代码中我们可以知道&#xff1a; 1&#xff0c;使用include引入check.php文件&#xff…

Excel制作工资表

需要用到的函数 函数要求如下&#xff1a; IFERROR 功能&#xff1a;处理公式中的错误&#xff0c;避免显示错误值。当公式产生错误时&#xff0c;使用自定义的值或表达式代替错误信息。 IFERROR(值, 错误值)SUM 功能&#xff1a;求和&#xff0c;计算一系列数字的总和。 语…

SSD |(七)FTL详解(中)

文章目录 &#x1f4da;垃圾回收&#x1f407;垃圾回收原理&#x1f407;写放大&#x1f407;垃圾回收实现&#x1f407;垃圾回收时机 &#x1f4da;解除映射关系&#x1f4da;磨损均衡 &#x1f4da;垃圾回收 &#x1f407;垃圾回收原理 ✋设定一个迷你SSD空间&#xff1a; 假…

Windows 和 Ubuntu通讯的网络设置

如果你是一个嵌入式工程师&#xff0c;因为工作需要&#xff0c;在linux下进行开发&#xff0c;一定会遇见配网问题。这篇文章解决Windows 和虚拟机Ubuntu通讯的网络设置的问题。 Windows的网络配置&#xff1a; 在配置网络前&#xff0c;先了解一下windows和ubuntu的网络构成…

CTFHUB技能树之SQL——过滤空格

开启靶场&#xff0c;打开链接&#xff1a; 既然是过滤空格&#xff0c;绕过空格的方法&#xff1a; 用/**/或%0a替代空格 &#xff08;1&#xff09;判断注入点 1 and 11# 会显示hacker 1/**/and/**/11# 有回显 1/**/and/**/12# 无回显&#xff0c;说明是整数型注入 &#…

嵌入式C++中内存分配基本实现方法

大家好,今天主要给大家分享一下,如何使用计算机中的内存空间进行分配,观察具体现象。 第一:C语言动态空间分配方式 第二:C++中动态内存分配方法 new 可以自动计算数据类型的大小 与 类型的转换 malloc 只能手动进行。 2.new 可以在分配空间的时候初始化 malloc 不行。 第三…

python采集汽车之家数据

python采集汽车之家数据 一、寻找数据接口二、发送请求获取响应三、解析数据四、完整代码一、寻找数据接口 如下图所示,在汽车之家首页点击报价图标: 在下图中选择价位,例如选择15-20万: 打开浏览器开发者工具,刷新页面,找到数据接口。接下来,通过翻页寻找接口url的变…

uni-app uni.setTabBarBadge 不生效

‘text’属性&#xff0c;类型必须是字符串&#xff0c;而接口返回的是数值&#xff0c;没有注意到&#xff0c;所以怎么都不生效&#xff0c;也不会有报错&#xff01;