开心锤锤2024年10月13日发布:c语言那些事儿:指针数组和数组指针傻傻分不清?

⭐发布日期:2024年10月13日 | 来源:开心锤锤

⭐作者:德丽·海明威 责任编辑:Admin

⭐阅读量:171 评论:6人

【新澳今晚开什么号码】

【新澳门今晚开奖结果+开奖号码】

【4949澳门开奖什么】 【新澳好彩免费资料查询水果奶奶】 【打开澳门网站资料】 【2024新奥历史开奖记录查询】 【2024年澳门管家婆免费资料查询】 【香港今晚六开彩结果 开奖结果查询结果久】 【澳门一肖一码免费期期准】 【澳门六开彩开奖结果和查询最新】
【2024澳门精准正版资料76期】 【新澳今天最新资料】 【2024澳门今晚开奖码】 【今天晚上澳门特马第四期】 【2024香港历史开奖记录】 【2024年澳门一肖一马期期准】 【2024全年资料免费大全优势生肖】 【2024澳门跑马图免费】

原本在我看来,“指针数组”和“数组指针”是两个并不相近的知识点。因为前一个的“主体”是数组,后一个的“主体”是指针,主体都不同。

虽然说数组可以看作是被const修饰的指针(常量类型的指针),但是这仅仅是为了理解方便,数组是分配在栈(stack)上的,而指针指向的内存,一般都是动态分配的,更多的是在堆(heap)上,使用起来要加倍小心,更为复杂(指针当然也可以指向栈上的数据)。

但是前几天我写了一篇剖析“常量指针”和“指针常量”的文章,在几个平台上发布之后,有一些朋友给我私信说,能不能写写“指针数组”和“数组指针”,也做一个“深度的解剖”,所以才有了今天这篇文章。

指针数组,其实说详细点,就是数组元素的类型是“指针”的数组。因为指针这个概念是不能独立存在的,必须要和具体的数据类型绑定在一起才有意义。所以,假设这里的指针是int型指针,那么我们可以这样定义:

int* array[3];

数组的名字是array,数组元素的类型是 int型指针(int*),这个数组一共有3个元素,没有被初始化。这个数组因为它的元素都是指针,我们称为“指针数组”。

总结一下,指针数组首先得是一个数组,然后它的元素类型一定是指针,满足这个条件就可以确定是“指针数组”了,只是要注意定义的格式,以免写错。

我们简单的举个例子,来对这个数组进行操作。

int* array[3];
int x,y,z;
array[0] = &x;
array[1] = &y;
array[2] = &z;
for(int i=0;i<3;i++){
	*array[i] = i * i ;
	printf("%d ",*array[i]);
}

这行代码的输出结果如下图:

程序运行的结果

首先定义一个指针数组和三个变量,然后将变量的地址赋值给数组的元素。最后通过数组元素间接的给变量赋值,并演示了通过数组元素显示变量的“值”,核心在于始终记得数组元素就是一个指针就可以了。

另外,指针数组可以是任意维的数组,比如我们定义一个二维的指针数组,并且对第三个元素赋值(变量的地址):

int* array[][3];
int x = 3;
array[0][2] = &x;

二维数组概念此处不展开,因为后面数组指针里要说到。

数组指针,说详细点,就是指向某种类型的数组的指针。核心在于这次不是数组,而是指针。只是这个指针指向的是“数组”。因为数组和指针一样,不是一种数据结构,必须要和某个数据类型绑定在一起才有意义,假设这个数组是int型数组,那么我们可以这样定义:

int (*pointer)[3];

这样写,确实看起来很别扭。如果改成这样:int[3] (*pointer);我们可能看的更明白些。

int[3] 是数组类型,有3个元素,(*ponter)是指针,和 int[3]结合起来,就是指向int[3]整型数组的pointer指针了。但是很遗憾,c语言不支持这样的写法

我再次强调一下,“数组指针”,是一个指针,这个指针特别的地方在于它不是指向一个普通的变量,而是指向一个数组结构(对,不是数据结构)。

也就是说它的“值”是一个数组的地址。通常我们都把数组名作为数组的地址对待,或者数组首元素的地址作为数组的地址对待,这两者在一般情况下是没有区别的(仅在一般情况下,此处不展开)。

因此,我们很容易就可以写出给数组指针赋值的语句,比如用数组名给数组指针pointer赋值:

int (*pointer)[3];
int array[3];
pointer = array;

或者,将数组首元素的地址赋值给数组指针pointer:

int (*pointer)[3];
int array[3];
pointer = &array[0];

当然也可以给数组指针pointer赋值一个匿名数组:

int (*pointer)[3];
pointer = (int[]){1,2,3};

无论如何,我们的数组指针已经指向了一个“数组”。那么我们如何通过数组指针来访问它说指向的数组的每一个元素呢?

我们尝试着这样:

int (*poiter)[3];
int array[3];
pointer = array;
pointer[0] = 1;//error

我们认为pointer = array; 说明pointer和array其实指向了同一个地址,那么通过指针pointer访问array的第一个元素,和array去访问第一个元素的用法应该一样才对啊。但为什么array[0]可以,pointer[0]不可以呢?

实际上,你应该能想到,不可以才是正确的,因为假设可以,那么下面这段代码:

int array[3];
int *ptr = array;
ptr[0] = 1;

ptr去访问array的元素是可以的,实际上此时的ptr和array就是等价的,如果上面的pointer也可以这样,那么就意味着pointer和ptr是等价的,因为pointer和array等价,ptr和array也等价。

可是这样一来,就出现了悖论,因为一个是指向“数组”的指针,一个是指向“普通变量”的指针,明显不同的指针类型,怎么可能等价呢?

我想这大概才是很多人迷惑的原因吧!

实际上,在之前的一些文章里,我提到过,这里的ptr虽然可以被数组名直接赋值,但实际上它指向的实际上不是数组,而是数组的第一个元素的地址。这有什么不同呢?

我其实不想把一个问题解剖的太细,因为这样会增加复杂度,但是在这里有必要稍微详细说一下。

数组名的“值”和数组第一个元素的地址的“值”看起来是同一个值,也可以相互混用去给别的指针赋值,但是实际上他们代表的含义是完全不同的。

数组名代表的是整个数组的地址,比如这个数组的元素是3个int型,假设在你的系统环境里int占据4个字节,那么数组名实际上代表的是占据了12个字节的这个内存块的地址。

而数组首个元素的地址,代表的是这个元素在内存中所占据的4个字节的内存地址。只是他们两者的“值”是相同的,所以我们就经常混用,而不加以区分了。

所以,你应该意识到 ptr = array;不是准确的写法。正确的写法是 ptr = &array[0]; 因为ptr它是一个指向“普通变量”的指针,而array[0]是一个普通变量,array不是,他是很多相同类型的普通变量组合成的一个“特殊”类型。

感谢你看到这里,你真的很有耐心。

因此,pointer指向的是这样一种情况:一个内存块是由一个或多个数组组成的,而pointer指向了这个内存块的地址(就是首地址)。

假设这个内存块由两个数组组成,其实就是一个“二维数组”。比如:

int two_col_array[2][3];
int (*pointer)[3];
pointer = two_col_array;

那么,显而易见pointer[0]其实就是two_col_array第一个数组的地址,pointer[1]其实就是two_col_array第二个数组的地址。

那么下面这几条语句都是等价的:

pointer = two_col_array;
pointer = two_col_array[0];
pointer[0] = two_col_array;
pointer[0] = two_col_array[0];

当这个内存块只有一个数组时,实际上就是一个一维数组,比如:

int array[3];
int (*pointer)[3];

那么以此类推,下面这几条语句也是等价的:

pointer = array;
pointer = &array[0];
pointer[0] = array;
pointer[0] = &array[0];

只是在二维数组中,其中某个一维数组的名字仍然是地址,而在一维数组中,只有pointer[0],没有pointer[1]而已。

所以回到最初,当我们想通过pointer修改指向的数组的元素的值时,我们只要把pointer看成是一个“二维数组的名字”就可以了。比如:

int array[3];
int (*pointer)[3] = array;
pointer[0][0] = 99;
pointer[0][1] = 520;
pointer[0][2] = 1314;

我们通过pointer把数组array的3个元素分别赋了值。

我们再举一个略显复杂的例子来看一看(没用循环赋值,是为了把二维数组的特点体现的更明显一点):

int a,b,c,d;
int* p_array[][2] = {{&a,&b},{&c,&d}};
int* (*pointer)[2] = p_array;
*pointer[0][0] = 1;
*pointer[0][1] = 2;
*pointer[1][0] = 3;
*pointer[1][1] = 4;
for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			printf("%d ",*pointer[i][j]);
	} 
}

pointer指向的是一个二维数组,这个二维数组是一个指针数组,这个例子是为了演示数组指针和指针数组在一起时该如何使用。

如果你对二维数组稍微了解些的话,你就已经意识到了所谓的数组指针其实和二维数组是很相似的。

学习编程的最好办法,除了多写代码,就是将近似的知识点在一起比较分析,这是最快的学习方式。

今天这个主题就讲到这里,其实还有很多可以展开的知识点,比如二维数组在内存中仍然是顺序存放的,以此类推,无论多少维的数组,在内存中其实都是线性存储的。

由此可见,多维数组只是我们逻辑上的一种表示方法,并不是物理上的存储方法。那么,数组指针是不是就可以和二维数组一样去使用呢?他们有没有异同?等等,感兴趣的朋友可以继续深挖。

另外,我的文章里的示例代码都没介绍编译器和系统环境,因为太多了,我经常换着用,所以很难每次都罗列一下,所以大家编译时有差异,并且困惑的时候,可以私信我交流沟通。

段誉,2024.1.29,写于合肥。

【新澳门开奖记录视频】 【澳门赛马会资料最准一码】
【2024今晚澳门开特马开什么】 【二四六香港天天开好彩】
【澳门最精准正最精准龙门】 【2024澳门正版开】
【香港澳门今晚六合最准彩资料】 【新澳门2024年澳门开奖结果】
【2024年新澳门天天开好彩大全】 【澳门一肖一码一中一肖】
【新澳历史查询结果】 【新澳天天彩免费资料】 【老澳门六开彩开奖网站】
上一条新闻 下一条新闻

推荐文章

发表评论

Isaiah

5秒前:正确的写法是 ptr = &array[0]; 因为ptr它是一个指向“普通变量”的指针,而array[0]是一个普通变量,array不是,他是很多相同类型的普通变量组合成的一个“特殊”类型。

IP:70.80.8.*

叶山玲子

6秒前:int x,y,z;

IP:16.31.7.*

McMahon

6秒前:因为数组和指针一样,不是一种数据结构,必须要和某个数据类型绑定在一起才有意义,假设这个数组是int型数组,那么我们可以这样定义:int (*pointer)[3];这样写,确实看起来很别扭。

IP:36.57.3.*

开心锤锤APP介绍

APP图标

澳门传真资料查询2024年APP名:开心锤锤

版本:V4.67.536

更新时间:2024-10-12 22:22

澳门特马网站这是一个功能强大的新澳门澳精准大全APP,可以帮助你完成各种任务。包括最新24小时热点资讯,今日最新:pointer = (int[]){1,2,3};无论如何,我们的数组指针已经指向了一个“数组”。

2024澳门码今晚开奖结果是什么APP介绍

APP图标

2024澳门正版免费料大全精准APP名:开心锤锤

版本:V6.42.345

更新时间:2024-10-12 19:15

无论是澳门一码一肖100快速浏览新闻还是深入了解某个话题,这款新闻APP都能为您提供全面、精准的信息服务。

2024年澳门正版免费APP介绍

APP图标

香港二四六308Kcm天下彩APP名:开心锤锤

版本:V6.77.526

更新时间:2024-10-12 22:22

澳门一肖一码一必开一肖应用界面简洁易用,用户可以轻松浏览头条新闻、深度报道和特写文章。24小时内的热点资讯一目了然,让您随时掌握世界动态。此外,您还可以参与评论,与其他读者交流看法,形成一个互动活跃的社区。

2023澳门六今晚开奖结果出来,生财有道APP介绍

APP图标

2024老澳历史开奖记录APP名:开心锤锤

版本:V2.38.125

更新时间:2024-10-12 13:20

澳门开奖记录开奖结果2024这款新闻APP是您获取实时信息的理想伴侣。它汇聚了全球最新的新闻报道,涵盖政治、经济、科技、娱乐、体育等多个领域。通过个性化推荐功能,您可以根据兴趣定制新闻源,确保每条信息都与您相关。

2024澳门精准传真APP介绍

APP图标

奥门2024正版资料免费看APP名:开心锤锤

版本:V9.49.865

更新时间:2024-10-12 20:20

这是一款功能强大的新旧澳门彩最新开奖记录应用,专为帮助您高效完成各种任务而设计。它不仅提供最新的24小时热点资讯,还为您带来今日的最新动态:*pointer[0][1] = 2; 。无论是获取信息还是提升效率,这款APP都是您理想的助手。

2024年正版资料全年资料大全APP介绍

APP图标

新澳门彩历史开奖记录走势图APP名:开心锤锤

版本:V5.47.303

更新时间:2024-10-12 20:19

这是一款功能强大的新澳历史开奖最新结果2024年应用,旨在帮助您高效完成各类任务。它提供最新的24小时热点资讯,让您随时了解发生的重大事件。今天的最新内容包括:pointer = two_col_array;那么,显而易见pointer[0]其实就是two_col_array第一个数组的地址,pointer[1]其实就是two_col_array第二个数组的地址。,为您的生活和决策提供了重要参考。这款APP是您获取信息和完成任务的得力助手。

澳门6合开奖结果记录查询最新消息APP介绍

APP图标

澳门2024正版资料大全完整版APP名:开心锤锤

版本:V9.58.164

更新时间:2024-10-12 21:13

这是一款功能强大的管家婆期期四肖四码中特管家应用,专为帮助您高效完成各种任务而设计。它汇集了最新的24小时热点资讯,让您时刻掌握世界动态。今日的最新内容包括:学习编程的最好办法,除了多写代码,就是将近似的知识点在一起比较分析,这是最快的学习方式。,为您的决策和日常生活提供有价值的信息支持。无论您需要了解什么,这款APP都能成为您不可或缺的助手。

香港今晚开特马+开奖结果66期APP介绍

APP图标

2024新奥历史开奖记录69期APP名:开心锤锤

版本:V3.63.809

更新时间:2024-10-12 14:21

今天的最新动态包括:int array[3]; ,让您第一时间掌握关键资讯,做出明智的决策。这个应用不仅是您的信息获取工具,更是一个提升生活质量的得力助手。

澳门选一肖一码一码资料APP介绍

APP图标

管家婆精选心水资料网APP名:开心锤锤

版本:V9.83.433

更新时间:2024-10-12 24:13

这是一款功能强大的2023澳门正版资料免费大全应用,能够帮助你高效地完成多种任务。它包括最新的24小时热点资讯,以及今天的最新动态:} 。

新澳六开彩资料2024APP介绍

APP图标

香港天天二四六开奖论坛APP名:开心锤锤

版本:V9.28.246

更新时间:2024-10-12 21:16

这款功能强大的2024澳门今晚开奖结果应用旨在提升您的日常效率,帮助您轻松应对各种任务。应用界面友好直观,用户可以快速导航,获取所需信息。它不仅提供最新的24小时热点资讯,还定期更新各种主题的文章和评论,确保您始终走在信息的前沿。

澳门今期开奖结果号码APP介绍

APP图标

2023澳门天天六开彩开奖结果APP名:开心锤锤

版本:V5.52.535

更新时间:2024-10-12 17:22

这款新闻APP是您获取实时新闻的最佳选择。它整合了全球各大新闻来源,提供最新的头条、热点和专题报道,涵盖从政治到娱乐的各个领域。用户可以根据兴趣自定义新闻推送,确保获取最相关的信息。

澳门一码中精准一码免费中特论坛APP介绍

APP图标

二四六香港资料期期准2024APP名:开心锤锤

版本:V9.82.311

更新时间:2024-10-12 18:15

APP界面友好,支持快速浏览和离线阅读。您还可以通过搜索功能,快速找到特定主题的新闻。互动功能让您可以评论、分享文章,与朋友讨论热点话题。无论您是在通勤、休闲,还是工作间隙,这款APP都能让您轻松掌握最新动态。