鱼C论坛

 找回密码
 立即注册
查看: 2684|回复: 15

[已解决]数组指针

[复制链接]
发表于 2022-11-13 16:45:07 | 显示全部楼层 |阅读模式

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

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

x
int temp[5]={1,2,3,4,5};
int (*p2)[5]=&temp;
int i;
for(i=0;i<5;i++)
{
        printf("%d\n",*(*p2+i));    这里有没有大佬解释一下为什么*(p2+i)打印的是他们的地址;加了*就是打印他们的值
}
return 0;
最佳答案
2022-11-13 18:19:24
本帖最后由 xiaotubie 于 2022-11-14 03:49 编辑

temp是一维数组。所以&temp就是指向temp数组的指针,p2是这个一维数组temp的指针,所以*p2是数组, 当执行*p2+1这个表达式时   *p2这个数组会被转换为指向首元素1的指针,所以*p2+i 就指向数组第i个元素的指针,所以要外面再套一层*才能获取元素值。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-11-13 17:26:24 | 显示全部楼层
本帖最后由 jackz007 于 2022-11-13 18:00 编辑
int (*p2)[5]=&temp;
        p2 是个指向末维为 5 的二维数组的指针,p2 每增减 1 的跨度是 5 个 int 元素,从一个二级指针(int **) 到数组元素必须经过两级取值变现。例如,p2[ i ][j] 必须表达为 *(*(p2 + i) + j) 或者 *(* p2 + i * 5 + j),就是说,p2 前面必须有 2 个 ** 才能完成从二级指针到数组元素的转变。你所问的代码 * (p2 + i)p2 的前面只有 1 个 * 表达的只是一个一级指针
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-13 18:19:24 | 显示全部楼层    本楼为最佳答案   
本帖最后由 xiaotubie 于 2022-11-14 03:49 编辑

temp是一维数组。所以&temp就是指向temp数组的指针,p2是这个一维数组temp的指针,所以*p2是数组, 当执行*p2+1这个表达式时   *p2这个数组会被转换为指向首元素1的指针,所以*p2+i 就指向数组第i个元素的指针,所以要外面再套一层*才能获取元素值。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 03:42:11 From FishC Mobile | 显示全部楼层
jackz007 发表于 2022-11-13 17:26
p2 是个指向末维为 5 的二维数组的指针,p2 每增减 1 的跨度是 5 个 int 元素,从一个二级指针( ...

p2啥时候是二维数组的指针了,temp是二维数组?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 08:38:30 From FishC Mobile | 显示全部楼层
本帖最后由 jackz007 于 2022-11-14 08:56 编辑
xiaotubie 发表于 2022-11-14 03:42
p2啥时候是二维数组的指针了,temp是二维数组?


     temp 不是,但是,p2 是,在定义 p2 的时候,让 p2 指向了 temp ,这个没错,但是,却又把 p2 规划成了 int (*)[5] 型的指针,千真万确,是一个二级指针,不信,你打印一下 p2[0][3] 看看,是不是会打印出 4;你再打印一下 p2[3] 的值,看看是不是很大?因为,它是一个一级指针,和你问的问题一模一样。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 09:25:04 | 显示全部楼层
本帖最后由 xiaotubie 于 2022-11-14 09:40 编辑
jackz007 发表于 2022-11-14 08:38
temp 不是,但是,p2 是,在定义 p2 的时候,让 p2 指向了 temp ,这个没错,但是,却又把 p2 规 ...


什么是二级指针,指针指向的那个对象还是一个指针,但是p2是 int (*)[5] 类型,表示指针指向的是一个数组,数组能跟指针等起来?哪本教材告诉你 int (*)[5] 类型的指针 指向的也是一个指针?
p2[3]是什么?  p2是数组的指针,所以p2+3还是一个数组指针,所以*(p2+3)是一个数组,
p2[3]就是*(p2+3)  ,它是一个数组,把数组能够说成指针的,典型的数组和指针概念混乱,乱用。
p2[3]这个数组,只是在作为右值表达式的时候会被转换成首元素的指针来使用
但是譬如用于sizeof 和   &  就不会发生转换,还是表示数组。
然后你说打印p2[3]是吧,当我们传到printf中打印的时候,p2[3]作为右值表达式就又转换为指向首元素的指针,这个时候输出一个地址值
如果用于sizeof 你发现他输出的就是这个数组的大小,因为这个时候数组对象作为左值,他不会转换成指针
你认为p2[3]是一个指针,那请问如果把sizeof用于一个指针,它会输出数组的大小,还是这个指针中地址值的大小。


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

使用道具 举报

发表于 2022-11-14 09:42:58 | 显示全部楼层
xiaotubie 发表于 2022-11-14 09:25
什么是二级指针,指针指向的那个对象还是一个指针,但是p2是 int (*)[5] 类型,表示指针指向的是一个数 ...

        没错,二级指针就是指向指针的指针,int (*p2)[5] 就是一个地道的二级指针,和 array[3][5] 一模一样,数组能跟指针等同起来?我要大声说,Yes,一维数组就是一级指针,不要那么犟,好好补补课吧!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 09:48:51 | 显示全部楼层
jackz007 发表于 2022-11-14 09:42
没错,二级指针就是指向指针的指针,int (*p2)[5] 就是一个地道的二级指针,和 array[3][5] 一模 ...

我建议你去知乎上问问,指针能不能跟数组等同起来,2022年了,居然还能说出   一维数组就是一级指针,你现在就去问问,看看怎么被喷
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 09:54:01 | 显示全部楼层
xiaotubie 发表于 2022-11-14 09:48
我建议你去知乎上问问,指针能不能跟数组等同起来,2022年了,居然还能说出   一维数组就是一级指针,你 ...

         不用上知乎,试试这个代码
#include <stdio.h>

int main(void)
{
        int temp[5]={1,2,3,4,5}                                             ;
        int (*p2)[5] = & temp                                               ;
        printf("p2[0][3] = %d , & p2[0][3] = %d\n" , p2[0][3] , & p2[0][3]) ;
        printf("temp[3] = %d , & temp[3] = %d\n" , temp[3] , & temp[3])     ;
}
       编译运行实况:
D:\[00.Exerciese.2022]\C>g++ -o x x.c

D:\[00.Exerciese.2022]\C>x
p2[0][3] = 4 , & p2[0][3] = 2293572
temp[3] = 4 , & temp[3] = 2293572

D:\[00.Exerciese.2022]\C>
        你能解释一下结果吗???
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 10:11:36 | 显示全部楼层
本帖最后由 xiaotubie 于 2022-11-14 10:19 编辑
jackz007 发表于 2022-11-14 09:54
不用上知乎,试试这个代码

       编译运行实况:


我发现你是真的不懂,完全混乱 ,回答完这个,我不想再跟你扯这种问题

p2指向temp数组的指针,所以p2[0][3]     第一步p2[0]   先转换为  *(p2+0)  它是一个数组,然后再参与到表达式中进行[3]运算,这个时候 *(p2+0)这个数组先转换为指向首元素1的指针,再对该指针进行[3]运算得到元素4
& p2[0][3]  因为上面分析出p2[0][3]是元素4  所以进行&运算获得元素4的指针,打印的时候获得元素4的地址


再看 temp[3] ,  temp是数组,参与到[3]进行表达式运算   temp转换为首元素的指针,最后相当于*(temp+3)   其实temp+3就是指向元素4的指针,最后通过*获取元素4
&temp[3] 获取元素4的指针

最后推荐你看一本书《C:A  Reference Manual》作者是 C/C++ 标准委员会的成员,里面讲解了数组的完整运算,以及数组什么时候会转换为指针,什么时候不会转换。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 10:27:23 | 显示全部楼层
本帖最后由 jackz007 于 2022-11-14 10:33 编辑
xiaotubie 发表于 2022-11-14 10:11
我发现你是真的不懂,完全混乱 ,回答完这个,我不想再跟你扯这种问题

p2指向temp数组的指针,所以p ...


        在铁一般的事实面前居然还能如此振振有词我也是醉了!!!
        既然事实说服不了你,你也别试图说服我,你坚持你的,我坚持我的,井水不犯河水
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 10:37:59 | 显示全部楼层
本帖最后由 dolly_yos2 于 2022-11-14 10:47 编辑
xiaotubie 发表于 2022-11-14 10:11
我发现你是真的不懂,完全混乱 ,回答完这个,我不想再跟你扯这种问题

p2指向temp数组的指针,所以p ...


好像不是第一次发现需要有回复回复多个帖子的功能了
来看看标准吧(第 6.5.2.1 节,关于 Array subscripting )
1. One of the expressions shall have type "pointer to complete object type", the other expression shall have integer type, and the result has type "type".
2. A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2 -th element of E1 (counting from zero).
3. Successive subscript operators designate an element of a multidimensional array object. If E is an n-dimensional array (n ≥ 2) with dimensions i × j × · · · × k, then E (used as other than an lvalue) is converted to a pointer to an (n - 1)-dimensional array with dimensions j × · · · × k. If the unary * operator is applied to this pointer explicitly, or implicitly as a result of subscripting, the result is the referenced (n - 1)-dimensional array, which itself is converted into a pointer if used as other than an lvalue. It follows from this that arrays are stored in row-major order (last subscript varies fastest).
4. EXAMPLE Consider the array object defined by the declaration int x[3][5]; Here x is a 3 × 5 array of int s; more precisely, x is an array of three element objects, each of which is an array of five int s. In the expression x[i], which is equivalent to (*((x)+(i))), x is first converted to a pointer to the initial array of five int s. Then i is adjusted according to the type of x, which conceptually entails multiplying i by the size of the object to which the pointer points, namely an array of five int objects. The results are added and indirection is applied to yield an array of five int s. When used in the expression x[i][j], that array is in turn converted to a pointer to the first of the int s, so x[i][j] yields an int.

水平有限,我先只做搬运,属于是自作多情,两位大佬可以参照
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 10:38:18 | 显示全部楼层
本帖最后由 xiaotubie 于 2022-11-14 10:39 编辑
jackz007 发表于 2022-11-14 10:27
在铁一般的事实面前居然还能如此振振有词我也是醉了!!!
        既然事实说服不了你,你也 ...


在这里争没啥用,你可以去别的地方问问,问问知乎上前面几个回答问题最多的,通常也是知乎的大牛,到底数组等不等同指针,让你问,你又不敢,自己一个人在这边一直认为,有意思吗?
你就直接发 一维数组就是一级指针,看看别人怎么回答你
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 10:40:11 | 显示全部楼层
jackz007 发表于 2022-11-14 10:27
在铁一般的事实面前居然还能如此振振有词我也是醉了!!!
        既然事实说服不了你,你也 ...

https://fishc.com.cn/forum.php?m ... p;page=1#pid6049692
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 10:53:40 From FishC Mobile | 显示全部楼层
dolly_yos2 发表于 2022-11-14 10:40
https://fishc.com.cn/forum.php?mod=viewthread&tid=220712&page=1#pid6049692

        我知道数组和指针二者不能划等号,在这里,我不想和你们玩文字游戏,我只强调实用,虽然二者不能完全划等号,但是,并不妨碍在访问数组的时候,却是可以完全等同使用的,这一点能否认吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 11:07:11 | 显示全部楼层
本帖最后由 xiaotubie 于 2022-11-14 12:09 编辑
jackz007 发表于 2022-11-14 10:53
我知道数组和指针二者不能划等号,在这里,我不想和你们玩文字游戏,我只强调实用,虽然二者不能 ...


其实数组就是数组,数组名也只不过是数组的标识符,代表数组这个对象,这块内存空间。
就像int a=1  这个a表示这个int 类型的1对象一样,标识这块内存空间

但是数组在作为右值表达式使用的时候,会被转换成指针来参与其中,也只是被转换成指针使用。譬如通常用于打印输出,或者下标运算等都转换为了指针。毕竟我们要获取里面的数据,那把数组名转换成首元素的指针来用,是比较好的方法

但是如果数组作为不可修改左值的时候,它还是代表它,即数组。譬如用于& 和sizeof , &数组名获得数组的指针,sizeof就算这个数组的对象大小,这个时候数组不会发生转换。

如果数组名就是指针的话,你用sizeof也不可能算出数组的大小了,同样二维数组名是二级指针的话,你也不可能计算出二维数组的大小,sizeof用于指针只会算出这个指针的大小,一个32位系统下4字节。而int ** 这种类型 (二级指针) 也无法跟二维数组名 的类型画上等号,
二维数组名转换成首元素的指针,指向的是一个数组,至于为何**二维数组名可以这样用,那是因为中间多了一个转换过程,看上去好像类似二级指针的间接访问。
而且  int a[2][3] 这种数组  我们对a这个转换后的指针执行两次**后   得到是是int类型的元素,正常的对应二级指针类型应该是  int**   而p是int (*)[3]。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-20 19:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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