啊涂涂 发表于 2018-9-16 11:41:24

关于指针....

#include <stdio.h>

int main()
{
                int temp = {1, 2, 3, 4, 5};
                int (*p2) = &temp;
                int i;
               
                for (i = 0; i < 5; i++)
                {
                                printf("%d\n", *(*p2 + i));
                }
               
                return 0;
}

整个程序表示看的不太明白,temp本身代表的就是一个地址,再加一个取地址运算符是什么意思呢?

而且下面这个 *(*p2 + i)这里也看的不太懂,搞不明白是怎么实现最后的结果的。

望大神赐教!!!

moc 发表于 2018-9-16 12:14:12

本帖最后由 moc 于 2018-9-16 12:18 编辑

int temp = {1, 2,3,4, 5};    这句话的意思是定义一个数组,temp是数组的首地址,也就是一个指针,他的类型是数组元素的类型,也就是说temp可以理解为指向整型类型的指针;它的步长是4个字节(int);
&temp 表示的含义是它是一个指向该数组类型(int)的指针,它的步长是数组元素个数乘sizeof(int);
int (*p2)的意思是定义了一个指向int数组类型的指针,那么自然可以让他指向上面的数组类型即&temp;
*(*p2+i)就是p2 [ i ][ 0 ]也即temp[ i ][ 0 ],也就是temp[ i ]
不知道明白了么?

TyCk 发表于 2018-9-16 12:21:28

作为数组,temp的值确实是一个地址,加上取址运算符是为了程序的可读性,让人一看就知道,这里用的是变量temp的地址,无论temp本身的类型是什么。

*(*p2+i),这里,假设i=1,也就是*(*p2+1)
*p2是取值,p2的值是数组第一个元素的地址,所以这里取的是数组的第一个元素的值1,加一呢,就是2,*2,就是取内存地址为2的值。
这样说,可能比较绕,但仔细理一下逻辑。
然后,大概会说,取内存地址2的值,不是可能报错么?是有可能的,这里应该是为了和 *(*(p2+1)) 区分,后者就是取数组第2个元素的值,因为后者是对指针的值,也就是元素的地址进行操作,会按照定义的数组类型进行加减,换句话说,假设int占2个字节,那么指针加1以后,就是到了数组指针的第二个元素,就是取数组第二个元素的值了.

{:10_266:}{:10_266:}很绕……

claws0n 发表于 2018-9-16 12:36:58

本帖最后由 claws0n 于 2018-9-16 16:57 编辑

用手机果然不方便......
取址对于非常量 non scalar(就是不是单一个数据的【量】)来说是可以省略的,添加可读性而已。

至于下面的用法是因为跨度的问题。指针解引用你了解?就是说 int *p = &a; 那么放在等号右边时*p == a 的值。

如果这样写int *p1 = temp; *(p1 + i);
int *p2 = *(*p2 + i);
p1 的跨度为 1,加一时,就是第二个元素了,然后解引用。
p2 的跨度为 5,如果直接加一,会指向第六个元素,已经越界。所以先解引用,成为指向第一个元素的指针,再选择偏移量。

wjp 发表于 2018-9-16 13:01:13

我是这么理解的(*p2)数组,所以*p2可以看做是数组名,所以*p2=temp,所以p2=&temp,*(*p2+i)...*p2=temp所以*p2指向数组第一个元素+i偏移到第i个元素的地址,在解引用得出第i个元素的值

claws0n 发表于 2018-9-16 13:22:10

wjp 发表于 2018-9-16 13:01
我是这么理解的(*p2)数组,所以*p2可以看做是数组名,所以*p2=temp,所以p2=&temp,*(*p2+i)...*p2= ...

一维数组是不需要的,高维数组才需要。主要是跨度问题,不然做不到直接索引。

最终的执念 发表于 2018-9-16 13:39:00

堆地址 和 栈地址是不一样的   temp是local 本地变量

但是temp作为一个指针指向了堆地址的空间

明白?

longff9009 发表于 2018-9-16 17:39:47

知识依据:int(*p)   p是指向由m个整型元素组成的一维数组的指针变量(谭浩强的《C程序设计》)
1、数组名temp本身数组第一个地址,(temp+i)则表示temp的地址,步长为1个元素的长度(1个int)。
2、&temp虽然也是一个地址,但它指向整个数组,步长为整个数组的总长度(5个int)
3、int(*p) 定义了一个指针变量p,它指向包含5个整型元素的整个一维数组(5个int),p每跳转一次,就会移动5个int的长度,因此从指针的类型上来说,&temp才与p是等价的,而不能把temp赋给p,二者的步长完全不同。
4、既然 p=&temp(这里“=”是数学中的等号,不是赋值运算),那么同时在前面加上 *号来取值则写成: *p= *(&temp),等号右边其实就是temp本身了。继续同时跳转i,*p+i =temp+i。最后在同时取值:
*(*p+i)=*(temp+i),而*(temp+i)即temp,因此程序输出数组元素的值。

longff9009 发表于 2018-9-16 17:44:59

longff9009 发表于 2018-9-16 17:39
知识依据:int(*p)   p是指向由m个整型元素组成的一维数组的指针变量(谭浩强的《C程序设计》)
1、数 ...

int *p表示的是一个数组,每个数组元素都是一个int 型指针变量
int (*p) 表示的就是一个指针,只是该指针类型有些不一样罢了

longff9009 发表于 2018-9-16 17:46:04

wjp 发表于 2018-9-16 13:01
我是这么理解的(*p2)数组,所以*p2可以看做是数组名,所以*p2=temp,所以p2=&temp,*(*p2+i)...*p2= ...

int *p表示的是一个数组,每个数组元素都是一个int 型指针变量
int (*p) 表示的就是一个指针,只是该指针类型有些不一样罢了

啊涂涂 发表于 2018-9-16 19:12:05

首先非常感谢大家前来帮忙,感激不尽,感谢每位鱼油的热心帮忙{:10_282:}!!!但是本小白真的还是有点一头雾水的感觉{:10_266:}

如果把&array理解为取字符串第一个数字的地址这很容易理解,但在学习这课的过程中,小甲鱼一直在强调 array != &array。

后者是把一个数组当做整体来看待的,取的是一整个数组的地址。但是如果这个是以整个数组为地址进行偏移的话,岂不是会移动到下一个数组里去?

还有就是对“步长”这块的含义不是特别清楚,是不是 array和&array除了在步长方面,别的方面都一样?{:10_245:}

啊涂涂 发表于 2018-9-16 19:15:03

还有就是这里

#include <stdio.h>

int main()
{
      int array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
      int *p = (int *)(&array + 1);

      printf("%d\n", *(p - 6));

      return 0;
}

这个&array + 1怎么就表示的是跑到数组最后一个元素的位置去了?

啊涂涂 发表于 2018-9-16 19:20:30

int temp = {1, 2, 3, 4, 5};
                int (*p2) = &temp;
                int i;
               
                for (i = 0; i < 5; i++)
                {
                              printf("%d\n", *(*p2 + i));
                }

int main()
{
      int array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
      int *p = (int *)(&array + 1);

      printf("%d\n", *(p - 6));

*(*p2 + 1)和 (&array + 1)为什么就因为一个*号,两者差别这么大?{:10_266:}

longff9009 发表于 2018-9-16 20:24:22

啊涂涂 发表于 2018-9-16 19:12
首先非常感谢大家前来帮忙,感激不尽,感谢每位鱼油的热心帮忙!!!但是本小白真的还是有点一头 ...

步长可以这样理解,不同类型的指针在跳转时要移动的位置长度不一样。既然指针本质都是存放地址的,那为什么还要指定int,float之类的类型呢?其实就是为了在实现指针跳转时明确移动多少位置,因为不同类型变量的存储方式和所占字节是不同的。例如,int *p ,那么p+1就意味着让地址值增加4个字节,而如果是float *p的话,p+1意味着让地址值增加8个字节,如果是 int (*p)的话,p+1就要增加这个5个int元素的数组所占的字节长度,所以跳一步确实是要跳完整个数组的,即数组的末尾后面了。搂主其实可以先理解二维数组,再回过头来看这个。

啊涂涂 发表于 2018-9-16 21:04:17

再次感谢其他楼层热心帮助的鱼油们,楼猪选了一个我个人比较能理解的答案{:10_256:}
页: [1]
查看完整版本: 关于指针....