妖娆乌龙茶 发表于 2023-11-2 19:18:23

一维数组指针疑问

#include<stdio.h>
int main()
{
int array={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的值是一样的,都是第二个元素的值?,两者指向的含义是不同的呀。

isdkz 发表于 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的值都是第二个元素的值。

希望这个解答能够解决你的疑问!如果还有其他问题,请随时提问。

Mike_python小 发表于 2023-11-2 19:19:38

问题分析:

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

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

解答:

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

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

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

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

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

总结:

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

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

球一个最佳答案谢谢啦!这对我非常重要!{:10_254:}{:10_254:}{:10_254:}

妖娆乌龙茶 发表于 2023-11-2 19:25:11

Mike_python小 发表于 2023-11-2 19:19
问题分析:

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

“pp+1 实际上跳过了整个数组 array 的长度。因此,输出结果仍然是数组 array 的第二个元素的值。”我也理解应该是下一个数组,但没有下一个数组,所以还是第二个元素的值?

xiaotubie 发表于 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 (*)类型的指针转换成了int*类型指针,开始的时候说过 &array和array的地址值是一样的,所以嘛,现在p其实和pp类型一致,值也是一致了都是首元素的指针,所以p+1当然和pp+1一致,指向了第二个元素。所以你引用的那个,他的说法其实不对, 什么叫跳过了整个数组,所以指向第二个元素,前后完全矛盾。pp是int*类型不是数组类型,怎么可能调过数组!

painx 发表于 2023-11-3 10:35:46

Mike_python小 发表于 2023-11-2 19:19
问题分析:

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

因为 array 是一个 int 数组,所以 pp+1 实际上跳过了整个数组 array 的长度
=============================
上面这句话我不太懂,跳过了整个数组的长度,岂不是指到数组外面的区域了吗?大佬能否再解释解释呀。

xiaotubie 发表于 2023-11-3 10:44:37

painx 发表于 2023-11-3 10:35
因为 array 是一个 int 数组,所以 pp+1 实际上跳过了整个数组 array 的长度
====================== ...

他的说法是完全错误的,array 是一个 int 数组没错,但是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个字节。

painx 发表于 2023-11-3 11:17:39

拿Clion+GCC试了一下,“int* pp=&array;”这种写法有warning
编译能过,结果是
p+1=1, pp+1=1

xiaotubie 发表于 2023-11-3 11:46:03

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

妖娆乌龙茶 发表于 2023-11-6 10:54:39

xiaotubie 发表于 2023-11-3 11:46


明白了十分感谢!
页: [1]
查看完整版本: 一维数组指针疑问