数组指针和指针数组

news2025/5/25 8:48:30

首先,理解一下数组指针和指针数组这两个名词:

“数组指针”和“指针数组”,只要在名词中间加上“的”字,就知道中心了——

数组的指针:是一个指针,什么样的指针呢?指向数组的指针。

指针的数组:是一个数组,什么样的数组呢?装着指针的数组。

然后,需要明确一个优先级顺序:()>[]>*,所以:

(*p)[n]:根据优先级,先看括号内,则p是一个指针,这个指针指向一个一维数组,数组长度为n,这是“数组的指针”,即数组指针;

p[n]:根据优先级,先看[],则p是一个数组,再结合,这个数组的元素是指针类型,共n个元素,这是“指针的数组”,即指针数组。

根据上面两个分析,可以看出,p是什么,则词组的中心词就是什么,即数组“指针”和指针“数组”。

int *p1[5]int (*p2)[5]

首先,对于语句“intp1[5]”,因为“[]”的优先级要比“”要高,所以 p1 先与“[]”结合,构成一个数组的定义,数组名为 p1,而“int*”修饰的是数组的内容,即数组的每个元素。也就是说,该数组包含 5 个指向 int 类型数据的指针,如图 1 所示,因此,它是一个指针数组。
在这里插入图片描述

其次,对于语句“int(p2)[5]”,“()”的优先级比“[]”高,“”号和 p2 构成一个指针的定义,指针变量名为 p2,而 int 修饰的是数组的内容,即数组的每个元素。也就是说,p2 是一个指针,它指向一个包含 5 个 int 类型数据的数组,如图 2 所示。很显然,它是一个数组指针,数组在这里并没有名字,是个匿名数组。
在这里插入图片描述
由此可见,对指针数组来说,首先它是一个数组,数组的元素都是指针,也就是说该数组存储的是指针,数组占多少个字节由数组本身决定;而对数组指针来说,首先它是一个指针,它指向一个数组,也就是说它是指向数组的指针,在 32 位系统下永远占 4 字节,至于它指向的数组占多少字节,这个不能够确定,要看具体情况。

数组指针 (*p)[n]

数组指针:是指针——指向数组的指针。

看下面的例子进行理解

#include "stdafx.h"
 
 
int main()
{
	//一维数组
	int a[5] = { 1, 2, 3, 4, 5 };
	//步长为5的数组指针,即数组里有5个元素
	int (*p)[5];
	//把数组a的地址赋给p,则p为数组a的地址,则*p表示数组a本身
	p = &a;
 
	//%p输出地址, %d输出十进制
	//\n回车
	//在C中,在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址,它的类型取决于数组元素的类型。
	printf("%p\n", a); //输出数组名,一般用数组的首元素地址来标识一个数组,则输出数组首元素地址
	printf("%p\n", p); //根据上面,p为数组a的地址,输出数组a的地址
	printf("%p\n", *p); //*p表示数组a本身,一般用数组的首元素地址来标识一个数组
	printf("%p\n", &a[0]); //a[0]的地址
	printf("%p\n", &a[1]); //a[1]的地址
	printf("%p\n", p[0]); //数组首元素的地址
	printf("%d\n", **p); //*p为数组a本身,即为数组a首元素地址,则*(*p)为值,当*p为数组首元素地址时,**p表示首元素的值1
	printf("%d\n", *p[0]); //根据优先级,p[0] 表示首元素地址,则*p[0]表示首元素本身,即首元素的值1
	printf("%d\n", *p[1]); //为一个绝对值很大的负数,不表示a[1]...表示什么我还不知道
 
	
 
	//将二维数组赋给指针
	int b[3][4];
	int(*pp)[4]; //定义一个数组指针,指向含4个元素的一维数组
	pp = b; //将该二维数组的首地址赋给pp,也就是b[0]或&b[0],二维数组中pp=b和pp=&b[0]是等价的
	pp++; //pp=pp+1,该语句执行过后pp的指向从行b[0][]变为了行b[1][],pp=&b[1]
 
	int k;
	scanf_s("%d", &k);
 
    return 0;
}
 
 
 

根据上面二维数组可以得出,数组指针也称指向一维数组的指针,所以数组指针也称行指针。

指针数组 *p[n]

指针数组:是数组——装着指针的数组。

看下面的例子进行理解:

#include "stdafx.h"
 
 
int main()
{
	int a = 1;
	int b = 2;
	int *p[2];
	p[0] = &a;
	p[1] = &b;
 
	printf("%p\n", p[0]); //a的地址
	printf("%p\n", &a); //a的地址
	printf("%p\n", p[1]); //b的地址
	printf("%p\n", &b); //b的地址
	printf("%d\n", *p[0]); //p[0]表示a的地址,则*p[0]表示a的值
	printf("%d\n", *p[1]); //p[1]表示b的地址,则*p[1]表示b的值
 
 
	//将二维数组赋给指针数组
	int *pp[3]; //一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2],所以要分别赋值
	int c[3][4];
	for (int i = 0; i<3; i++)
		pp[i] = c[i];
 
	int k;
	scanf_s("%d", &k);
 
    return 0;
}
 

最后,从上文来看:

数组指针是一个指针变量,占有内存中一个指针的存储空间;

指针数组是多个指针变量,以数组的形式存储在内存中,占有多个指针的存储空间。

了解指针数组和数组指针二者之间的区别之后,继续来看下面的示例代码:

int arr[5]={12345};
int (*p1)[5] = &arr;
/*下面是错误的*/
int (*p2)[5] = arr;

不难看出,在上面的示例代码中,&arr 是指整个数组的首地址,而 arr 是指数组首元素的首地址,虽然所表示的意义不同,但二者之间的值却是相同的。那么问题出来了,既然值是相同的,为什么语句“int(p1)[5]=&arr”是正确的,而语句“int(p2)[5]=arr”却在有些编译器下运行时会提示错误信息呢(如在 Microsoft Visual Studio 2010 中提示的错误信息为“a value of type"int"cannot be used to initialize an entity of type"int()[5]"”)?

其实原因很简单,在 C 语言中,赋值符号“=”号两边的数据类型必须是相同的,如果不同,则需要显示或隐式类型转换。在这里,p1 和 p2 都是数组指针,指向的是整个数组。p1 这个定义的“=”号两边的数据类型完全一致,而 p2 这个定义的“=”号两边的数据类型就不一致了(左边的类型是指向整个数组的指针,而右边的数据类型是指向单个字符的指针),因此会提示错误信息。

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

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

相关文章

Windows内核理论基础学习

文章目录 前言Windosw内核 理论基础Windows体系结构CPU权限级别内存空间布局Windows内核结构硬件抽象层&#xff08;HAL&#xff09;内核层执行体层设备驱动程序文件系统/存储管理网络 Windows子系统窗口管理图形设备接口 系统线程和系统进程 内核基本概念处理器模式内存管理进…

Vue3+TS+ElementPlus的安装和使用教程【详细讲解】

前言 本文简单的介绍一下vue3框架的搭建和有关vue3技术栈的使用。通过本文学习我们可以自己独立搭建一个简单项目和vue3的实战。 随着前端的日月更新&#xff0c;技术的不断迭代提高&#xff0c;如今新vue项目首选用vue3 typescript vite pinia……模式。以前我们通常使用…

git 管理vivado工程, tcl 恢复vivado工程

使用Git进行Vivado版本控制 english youtube 如果不是上边目录结果 , 参考上边目录结构 ,重新建一个工程; 在目录work下产生proj.tcl 修改proj.tcl 主要删除bd wrapper相关的部分; # Import local files from the original project set files [list \[file normalize…

【嵌入式】About USB Powering

https://www.embedded.com/usb-type-c-and-power-delivery-101-power-delivery-protocol/https://www.embedded.com/usb-type-c-and-power-delivery-101-power-delivery-protocol/ Type-C接口有多强&#xff1f;PD协议又是什么&#xff1f;-电子发烧友网由于Type-C接口自身的强…

详细分析MybatisPlus中的orderBy、orderByDesc、orderByAsc函数

目录 前言1. 概念2. API示例3. 实战 前言 实战中学习并进行补充该类的源码以及应用 1. 概念 在 MyBatis-Plus 中&#xff0c;orderBy、orderByDesc 和 orderByAsc 是用于构建 SQL 查询语句中的 ORDER BY 子句的方法。 这些方法都是通过 QueryWrapper 类的实例来调用的&…

提升代码托管,助力大数据学习!Git学习网站等你来挑战!

介绍&#xff1a;Git是一个开源的分布式版本控制系统&#xff0c;可以高效地处理各种规模项目的版本管理。它是Linus Torvalds为了帮助管理Linux内核开发而开发的开放源码版本控制软件。在Git中&#xff0c;你可以掌握工作区、暂存区和版本库等核心概念&#xff0c;并学会使用常…

SV-7042VP 15W sip网络有源音箱,可外接15W无源副音箱

SV-7042VP 15W sip网络有源音箱,可外接15W无源副音箱 一、描述 SV-7042VP是深圳锐科达电子有限公司的一款壁挂式SIP网络有源音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到功率15W。同时它可以外接一个15W的…

VSCode上远程调试代码出现的问题

记录一下&#xff1a; 真的是汗流浃背了&#xff0c;师妹叫帮忙如何在VSCode上远程调试代码&#xff0c;一些自己已经经历过的问题&#xff0c;现在已经忘记了。又在网上一顿搜索&#xff0c;这次记录下吧。。。 出现以下问题&#xff1a; 1. 终端界面总是sh-4.4 $ &#xff…

【自动化测试】转行人员在面试中被问及计算机基础知识该怎么办?????(长文,预计三小时阅读)

看前提示&#xff0c;本文共4W字&#xff0c;76道题&#xff08;附答案&#xff09; 全部看完预计三个小时&#xff0c;如果觉得时间长&#xff0c;可以直接跳转到文末&#xff0c;有本文的word版提供下载 近些年软件测试岗位从转行的来人越来越多&#xff0c;占比高达44% 软件…

OPENGL,GPU图形库Skia在Windows下编译多种VS版本的DLL

这几天刚改了改Duilib&#xff0c;之前为了让Duilib更好的支持透明异形窗体所以把Duilib改为Gdi和Gdi的双渲染引擎。于是想到了有时间就把渲染引擎完全独立为渲染接口&#xff0c;可以增加更多的渲染引擎。现在来说Skia是个很不错的渲染&#xff0c;之前我只是单独编译了VS2013…

论文查重降重写成大白话可以吗

大家好&#xff0c;今天来聊聊论文查重降重写成大白话可以吗&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 论文查重降重&#xff1a;用大白话解析 一、引言 写论文是每个…

软件测试基础理论学习-常见软件开发模型

瀑布模型 背景 瀑布模型的概念最早在1970年由软件工程师Winston W. Royce在其论文《Managing the Development of Large Software Systems》中提出。Royce虽然没有明确提出“瀑布模型”这个术语&#xff0c;但他描述了一种线性的、阶段性的开发流程&#xff0c;各个阶段之间具…

小迪安全第一天

一、常用的专业术语 参考&#xff1a; https://www.cnblogs.com/sunny11/p/13583083.html POC&#xff08;proof of concept&#xff09;验证漏洞的代码EXP(exploit) 利用对一段漏洞代码的利用Playload:有效载荷&#xff0c;当利用exploit成功后如何通过一个管道把这个权限给…

集群渲染是?渲染农场是?两者与云渲染关联是什么

在数字化浪潮不断推进的当下&#xff0c;渲染技术在多个行业中发挥着至关重要的作用&#xff0c;尤其体现在电影制作、建筑可视化以及电子游戏开发等领域。在众多渲染技术中&#xff0c;集群渲染、渲染农场以及云渲染特别受到业界的重视。本文旨在阐述这些概念的含义以及它们之…

蛇目标检测数据集VOC格式750张

蛇&#xff0c;一种令人着迷而又神秘的爬行动物&#xff0c;以其独特的外貌和习性&#xff0c;成为了自然界中的一道独特风景。 蛇的外观光滑细长&#xff0c;身体呈流线型&#xff0c;鳞片覆盖全身&#xff0c;使得它们能够在地面上或树枝间快速移动。大多数蛇拥有尖锐的毒牙…

小目标识别任务算法

小目标识别是计算机视觉领域中的一个挑战性任务&#xff0c;主要是指在图像或视频中检测和识别尺寸相对较小的目标。 以下是一些常见的小目标识别算法&#xff1a; Faster R-CNN&#xff1a; Faster R-CNN是一种基于深度学习的目标检测算法&#xff0c;通过引入区域建议网络&am…

算法导论复习——CHP22 基本图算法

图的表示 邻接矩阵和邻接表 稀疏图一般用邻接表表示&#xff08;稀疏图&#xff1a;边数|E|远小于的图 &#xff09; 稠密图更倾向于用邻接矩阵表示 (稠密图&#xff1a;边数|E|接近的图) 邻接矩阵可用于需要快速判断任意两个结点之间是否有边相连的应用场景。 如果用邻…

VSCode远程连接centos

1 下载remote -ssh插件 2 在上方打开命令面板&#xff0c;输入>,再输入ssh&#xff0c;选择设置 Remote-SSH:Settings 那行 3 勾选下面这个选项 4 点击加号旁边的那个齿轮&#xff0c;选择.ssh\config ,配置连接信息&#xff0c;保存好后&#xff0c;刷新。 4 连接centos,然…

springBoot2.3-简单了解依赖管理、自动配置

一、自动依赖管理 基本介绍&#xff1a;springBoot提前帮我们写好了极多的依赖及版本号&#xff0c;当然我们也可以自定义依赖项与版本号。 1.1 简单介绍 1、在入门案例中&#xff0c;springBoot的maven中引入了parent父工程 2、ctrl 左键 parent&#xff0c; 发现里边还有…

图像融合算法

图像融合是将两个或多个图像或图像的特定部分合并在一起的过程。这可以通过各种图像融合算法来实现&#xff0c;这些算法可以用于不同的应用&#xff0c;如图像编辑、计算机视觉和医学图像处理。以下是一些常见的图像融合算法&#xff1a; 透明度融合&#xff08;Alpha Blendi…