数组指针p,二维数组a[3][4]有如下赋值方法:*p = a[0]对吗

正确的赋值方法p = a;或者p = &a[0];
我之所以有题目的想法是建立在:
a存放的是a[0]的地址 a[0]存放a[0][0]的地址;
因为p = a,所以*p 等价于a[0]
或者因为:*和&符号互逆 根据p = &a[0]所以*p = *&a[0]所以*p = a[0]

有了前面的定义,*p==a[0]不错,但不能*p=a[0];这样赋值。因为有了p=a;后,*p(或p[0])、*(p+1)(或p[1])、*(p+2)(或p[2])它们都是常量指针,不能重新赋值。至于你说*和&是互逆运算也不是绝对的——对于一级指针和变量,*和&确实可以互逆;对于二级以上,*是取值,**是把第一次取出的值作为地址再取值,这是合法的,甚至***或更多也是合法的。但&&合法吗?显然不合法,因为&是取变量的地址,难道地址还有地址可以再用一个&去取吗?所以好多教科书上笼统说*、&互逆我并不赞同……个人理解,仅供参考。追问

你看一下我对上一个答主的反驳,没问题的话我就采纳你了

追答

采纳谁是你的事。但人家答“因为p = a,所以*p 等价于a[0]”这一点都不错,是说有了p = a;,*p 就是a[0]——而我的回答是说不能*p=a[0];,这原因不是因为*p不等于a[0](它们是相等的,有了p = a;后*p就已经等于a[0]了),而是因为*p是常指针,不能为其赋值。别说赋a[0],赋什么都不行;你可以试一下给a[0]赋一个值就不行,既然*p就是a[0],当然也不能给*p赋值了。因为常数不能作左值。当你**p时就是a[0][0],a[0][0]是个允许变更的元素(const修饰的除外),所以**p也是可以赋值的。所以采纳谁不重要,重要的是把“数组与指针”搞清楚——这里确实有点难度,但理解了指针的实质就并不复杂。所以我们的回答并不相悖。多说两句:声明int a[3][4];后,凡是a[x][y](0<=x<3,0<=y<4)都可以重新赋值,但a[x]是不能重新赋值的,因为它们是常指针(数组名)。那么,有了p=a;后,*p就是a[0],既然a[0]不能重新赋值,换个写法*p若能重新赋值那不乱套了?

温馨提示:答案为网友推荐,仅供参考
第1个回答  2018-07-19
“因为p = a,所以*p 等价于a[0]”
这里就是你的理解错误了。*p等价于a[0][0]的内容。
*p指针存放的是一个地址,不管经过了几次倒手,只要取内容就还是取出实际内容。
想要利用指向指针的指针,需要声明成**p并将其指向一个指针。追问

麻烦答主再看一下第二个回答(看到第二个句号就可以了),你们两的回答都能解释,但是理解好像是相悖的。
我认同他的解释,因为按照你的理解,那么我是不是可以直接打印*p,但是直接打印*p会警告,忽略警告打印错误(应该是十进制的地址)而打印**p是没有警告的而且能出正确答案

第2个回答  2018-07-19
int a[3][4] = {};
for (int i = 0; i < 3;i++)
{
    for (int j = 0; j < 4;j++)
    {   
    a[i][j] = i * 10 + j;
     }
}

我按你说的样子写了一个例子,运行出来的(a[3][4])内存片段如下:0x0036FC1C  00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 0a 00 00 00 0b 00 00 00 0c 00 00 00 0d 00 00 00 14 00 00 00 15 00 00 00 16 00 00 00 17

以上为16进制,翻译一下就是:0 1 2 3 10 11 12 13 20 21 22 23

可以看出,从a开始,a[0][0]--->a[3][4]是依次排列的,而且里面没有存放指针地址,而是直接存放的数据内容,所以你一开始的命题(a存放的是a[0]的地址 a[0]存放a[0][0]的地址;)就已经错了。

相似回答