鱼C论坛

 找回密码
 立即注册
查看: 1445|回复: 9

[已解决]一维数组指针疑问

[复制链接]
发表于 2023-11-2 19:18:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include<stdio.h>
int main()
{
int array[3]={0,1,2};
int* p=array;
int* pp=&array;
printf("p+1=%d, pp+1=%d\n",*(p+1),*(pp+1));
return 0;
}
为什么p+1的值与pp+1的值是一样的,都是第二个元素的值?,两者指向的含义是不同的呀。
最佳答案
2023-11-2 19:19:38
问题分析:

在C/C++中,数组名是数组首元素的地址。将数组名赋值给指针变量,可以得到指向数组首元素的指针。在给定一个指针变量时,对该指针进行加法运算时,实际上是对指针的值进行偏移。

在给定代码中,int* p = array;int* pp = &array; 分别将数组 array 的首地址赋值给指针变量 ppp。然后通过 ppp 进行加法运算,输出结果。

解答:

在给定的代码中,p+1pp+1 实际上是对指针进行加法运算,即将指针的值偏移了相应的字节大小。

虽然 ppp 都指向了数组 array 的首地址,但它们的类型是不同的。pint* 类型的指针,而 ppint (*)[3] 类型的指针,它表示一个指向具有3个整型元素的数组的指针。

由于 ppp 的类型不同,导致它们在进行加法运算时的行为也不同。

- 对于 p+1pint* 类型的指针,所以 p+1 表示指针 p 往后偏移了一个 sizeof(int) 的字节大小。因此,输出结果输出的是数组 array 的第二个元素的值。
- 对于 pp+1ppint (*)[3] 类型的指针,所以 pp+1 表示指针 pp 往后偏移了一个整个数组 array 的大小。因为 array 是一个 int[3] 数组,所以 pp+1 实际上跳过了整个数组 array 的长度。因此,输出结果仍然是数组 array 的第二个元素的值。

所以,尽管 ppp 的类型不同,但由于在加法运算中都实现了偏移操作,因此 p+1pp+1 都指向了数组 array 的第二个元素,并且输出结果相同。

总结:

- p+1pp+1 都进行了指针的偏移运算,但由于 ppp 的类型不同,导致了实际的偏移量不同。
- p+1 偏移了一个 sizeof(int) 的字节大小,而 pp+1 偏移了整个数组 array 的大小。

希望这个回答对你有所帮助。如果还有其他问题,请随时提问。

球一个最佳答案谢谢啦!这对我非常重要!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-11-2 19:18:36 | 显示全部楼层
首先,让我们来看看代码中的两个指针的定义和初始化:
int* p = array;
int* pp = &array;

p  是一个指向整型的指针,它被初始化为  array  的地址,也就是数组的第一个元素的地址。

pp  也是一个指向整型的指针,但它被初始化为  &array ,即整个数组  array  的地址。

接下来,让我们来看看打印语句中的表达式:
printf("p+1=%d, pp+1=%d\n", *(p+1), *(pp+1));

*(p+1)  表示  p  指针向后偏移一个整型单位,然后取该地址处的值。由于  p  指向数组的第一个元素,所以  *(p+1)  实际上是数组的第二个元素的值。

同样地, *(pp+1)  表示  pp  指针向后偏移一个整型单位,然后取该地址处的值。由于  pp  指向整个数组  array ,所以  *(pp+1)  实际上也是数组的第二个元素的值。

因此,虽然  p  和  pp  指向的含义不同,但是由于数组的第一个元素的地址与整个数组的地址相同,所以  p+1  和  pp+1  的值都是第二个元素的值。

希望这个解答能够解决你的疑问!如果还有其他问题,请随时提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-11-2 19:19:38 | 显示全部楼层    本楼为最佳答案   
问题分析:

在C/C++中,数组名是数组首元素的地址。将数组名赋值给指针变量,可以得到指向数组首元素的指针。在给定一个指针变量时,对该指针进行加法运算时,实际上是对指针的值进行偏移。

在给定代码中,int* p = array;int* pp = &array; 分别将数组 array 的首地址赋值给指针变量 ppp。然后通过 ppp 进行加法运算,输出结果。

解答:

在给定的代码中,p+1pp+1 实际上是对指针进行加法运算,即将指针的值偏移了相应的字节大小。

虽然 ppp 都指向了数组 array 的首地址,但它们的类型是不同的。pint* 类型的指针,而 ppint (*)[3] 类型的指针,它表示一个指向具有3个整型元素的数组的指针。

由于 ppp 的类型不同,导致它们在进行加法运算时的行为也不同。

- 对于 p+1pint* 类型的指针,所以 p+1 表示指针 p 往后偏移了一个 sizeof(int) 的字节大小。因此,输出结果输出的是数组 array 的第二个元素的值。
- 对于 pp+1ppint (*)[3] 类型的指针,所以 pp+1 表示指针 pp 往后偏移了一个整个数组 array 的大小。因为 array 是一个 int[3] 数组,所以 pp+1 实际上跳过了整个数组 array 的长度。因此,输出结果仍然是数组 array 的第二个元素的值。

所以,尽管 ppp 的类型不同,但由于在加法运算中都实现了偏移操作,因此 p+1pp+1 都指向了数组 array 的第二个元素,并且输出结果相同。

总结:

- p+1pp+1 都进行了指针的偏移运算,但由于 ppp 的类型不同,导致了实际的偏移量不同。
- p+1 偏移了一个 sizeof(int) 的字节大小,而 pp+1 偏移了整个数组 array 的大小。

希望这个回答对你有所帮助。如果还有其他问题,请随时提问。

球一个最佳答案谢谢啦!这对我非常重要!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-11-2 19:25:11 | 显示全部楼层
Mike_python小 发表于 2023-11-2 19:19
问题分析:

在C/C++中,数组名是数组首元素的地址。将数组名赋值给指针变量,可以得到指向数组首元素的指 ...

“pp+1 实际上跳过了整个数组 array 的长度。因此,输出结果仍然是数组 array 的第二个元素的值。”我也理解应该是下一个数组,但没有下一个数组,所以还是第二个元素的值?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-11-3 10:28:22 | 显示全部楼层
本帖最后由 xiaotubie 于 2023-11-3 10:35 编辑
妖娆乌龙茶 发表于 2023-11-2 19:25
“pp+1 实际上跳过了整个数组 array 的长度。因此,输出结果仍然是数组 array 的第二个元素的值。”我也 ...


array是数组首元素的指针,    &array是数组的指针,类型不一致,但是对应的地址数值是一样的。
因为类型不一致,所以array+1和&array+1结果不一样,array+1指向数组的第二个元素,而&array+1指向整个数组后面的下个数组,就算你没有定义下个数组,C语言还是会把跨越整个数组后的那一片内存当成数组。
这里int* pp = &array;  注意此时的pp只是一个int*l类型,跟数组完全没关系,pp+1只会前进一个int的长度。
正常情况下这样的赋值其实会报错的,前后类型不一致,假如一些不标准编译器没报错,那么其实发生了隐适转换,也就是说把int (*)[3]类型的指针  转换成了int*类型指针,开始的时候说过 &array和array的地址值是一样的,所以嘛,现在p其实和pp类型一致,值也是一致了  都是首元素的指针,所以p+1当然和pp+1一致,指向了第二个元素。所以你引用的那个,他的说法其实不对, 什么叫跳过了整个数组,所以指向第二个元素,前后完全矛盾。pp是int*类型不是数组类型,怎么可能调过数组!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-11-3 10:35:46 | 显示全部楼层
Mike_python小 发表于 2023-11-2 19:19
问题分析:

在C/C++中,数组名是数组首元素的地址。将数组名赋值给指针变量,可以得到指向数组首元素的指 ...

因为 array 是一个 int[3] 数组,所以 pp+1 实际上跳过了整个数组 array 的长度
=============================
上面这句话我不太懂,跳过了整个数组的长度,岂不是指到数组外面的区域了吗?大佬能否再解释解释呀。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-11-3 10:44:37 | 显示全部楼层
painx 发表于 2023-11-3 10:35
因为 array 是一个 int[3] 数组,所以 pp+1 实际上跳过了整个数组 array 的长度
====================== ...

他的说法是完全错误的,array 是一个 int[3] 数组没错,但是pp是定义成的int* 类型,所以pp+1只会前进一个int的大小。
int*pp = &array ;其实是要报错的,因为类型不一致,有些二逼编译器没报错,那么也只是拿到数组的地址值,并转换成int*类型。&array和array的地址值是一样的,类型不一致。所以这个时候p和pp其实是值一样,类型也一样,p+1和pp+1都是前进一个int的大小,因此都是指向了数组第二个元素
假设int是4字节,那么&array+1 是跨越整个数组,也就是前进了12个字节,而array+1是前进了4个字节。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-11-3 11:17:39 | 显示全部楼层
拿Clion+GCC试了一下,“int* pp=&array;”这种写法有warning
编译能过,结果是
p+1=1, pp+1=1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-11-3 11:46:03 | 显示全部楼层
painx 发表于 2023-11-3 11:17
拿Clion+GCC试了一下,“int* pp=&array;”这种写法有warning
编译能过,结果是
p+1=1, pp+1=1

图
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-11-6 10:54:39 | 显示全部楼层

明白了十分感谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-24 00:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表