C指针问题迷惑中,(*p)[4]和*p[4]和*p到底有什么区别?

自学,谭浩强的C语言书,多维数组指针变量,设有一个二维数组a[3][4],下面是书中原话:
“(2)指向由m个元素组成的一维数组的指针变量。
上例的指针变量p是指向整型变量的,p+1所指向的元素是p所指向的下一元素。可以改用另一方法,使p不是指向整型变量,而是指向一个包含m个元素的一维数组。这时,如果p先指向a[0](即p=&a[0]),则p+1不是指向a[0][1],而是指向a[1],p的增值以一维数组的长度为单位,见图10.28。”————看到这里,似乎说的是p指向的是二维数组a[3][4]的每一行的第一个位置,书中前面举出了一个排长、班长、列兵的例子,那么这里p应该是充当了排长的角色而指向的是班长吗?那么下面又给出了这样一个例子:

main()
{int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int (*p)[4],i,j;
p=a;
scanf("i=%d,j=%d\n",i,j,*(*(p+i)+j));
}
运行情况如下:
i=1,j=2 /*回车*/
a[1,2]=13

/*程序第3行 int (*p)[4] 表示p是一个指针变量,它指向包含4个元素的一维数组。*/

————那么这里有四个问题:
1 为什么要定义成(*p)[4]而不是(*p)[3]呢?前面不是说了p是指向“班长”也就是每一行的开头的吗?怎么看程序里好像是指向列了呢?

2 第4行代码中 p=a,所赋给p的是什么?是“班长”还是“列兵”?

3 再一个问题就是,为什么要用(*p)[4]这种方式呢?用一个*p,依次指一行中的每一元素,不是一样可以解决问题吗?(*p)[4]到底是什么意思?一开始认为它是一个数组,但书上意思却又说它不是。

以上说得比较多,也不知道大家看明白了没有,总之是感觉很迷惑,还望各位老师及师兄能一一给予详细的解答。多谢。
认真看了各位的回答,就是说,(*p)[4]只能指向一个有4个元素的数组的开头,而如果指向5个元素的数组或者指向其它类型就不行,

(*p)[4]是划分出1个内存单元,叫做指向数组的指针,在它后面加个[4]是为了方便用i*m+j公式计算地址用的。而*p[4]是划分出4个内存单元的数组(叫做指针数组)是吗?

p=a也就是把a里面的值(&a[0])赋给了p

以上是我的理解,不知道是否正确?还希望各位能够指点。

首先 二维数组 int a[3][4]的排列是这样的:
1 3 5 7
9 11 13 15
17 19 21 23
表示三行四列的二维数组

第一个问题,为什么是(*p)[4]而不是(*p)[3]
因为p是指向行,而每行可以看成是一个一维的有四个元素的数组,所以是(*p)[4]而不是(*p)[3],因为(*p)[3]是一个指向只含有三个元素的数组。

第二个问题:
p=a,是把这个数组a的起始地址赋给p,

第三个问题:
用一个*p,依次指一行中的每一元素也是可以实现的,但是数组指针解决一些特别的问题时会带来很大的方便。(*p)[4]首先是结合括号(*p),表示是一个指针,然后和[]结合,表示指向一个数组,所以(*p)[4]表示一个指向数组的指针
如果写成*p[4]的话,那么p首先和[]结合,表示p是一个数组,然后和*结合,表示这个数组元素是指针,所以*p[4]表示为一个含有四个指针的数组
温馨提示:答案为网友推荐,仅供参考
第1个回答  2009-01-10
回楼主的补充问题:

(*p)[4]只能指向一个有4个元素的数组的开头,而如果指向5个元素的数组或者指向其它类型就不行,后面加个[4]是为了方便用i*m+j公式计算地址用的.

(*p)[4]指向第一维有四个元素的二维数组,方便今后用p[i][j]的方式调用,但是如果指向了其他东西,C语言也是允许的,只不过用到p[i][j]是仍旧当他那样是第一维有四个元素的二维数组处理。

看了上述解释以后一头雾水也没关系,实际上C语言的指针是相当灵活的,它不检查指针的操作,所以他功能强大,也很危险。例如:

char a[8]={0,1,2,3,4,5,6,7};
int (*p)[4]=a;
printf("%d",p[0][2]); /* 1284 (等于5*256+4,即二进制00000101 00000100) */
printf("%d",p[1][3]); /*超过a范围,结果随机*/
printf("%d",p[-1][4]);/*256 相当于p[0][0]*/

上面这段东西我在tc里面试验,第二行有警告,编译仍然通过。本回答被提问者采纳
第2个回答  2009-01-06
p == a
*p == a[]
(*p)[4] == a[][4]
首先理解上面3个式子,“==”只是表示类型的共同性。

a[3][4]可以看成a表示的二维数组 也可以看成“a[3]”表示的一维数组
(*p)[4]可以看成是(*p)的数组。

再注意数组在内存中是按a[0][0] a[0][1] ... a[0][3] a[1][0] ... 这样的顺序存储的

因此对一维数组a[n]等价于*(a+n)等价于*((&a[0])+n)
对二维数组a[n][m]等价于*((&a[n][0])+m)等价于*(a[n]+m)等价于*(*(a+n)+m)

如果写的不对 希望高手指出。但总的思想就是弄清楚地址、指针和值的关系就OK了。
第3个回答  2009-01-06
C语言中数组与指针是“一套班子两块牌子”,也就是说这个程序中如果出现*(a+3),p[1][2]这样的操作也是合法的。
声明数组a时,系统自动按照如下顺序安排内存[0][0],[0][1],[0][2],[1][0],[1][1],[1][2]......
指针变量里储存的是内存地址,如果令指针p指向[0][0]的那么p+1就是[0][1]的地址p+0*3+2指向的是[0][2],p+2*3+1就是[2][1]。

明确以上问题后,你的问题就明了了

1。(*p)[4]是指向二位数组的指针,其第一维是4,第二维随意,如果程序中有p[i][j]相当于*(p+i*4+j)
2。p=a 相当于 p=&a[0] 就是把a[0]的地址给p,此处a[0]是int型,a是数组型,同时也是int指针。
3。(*p)[4]告诉系统p[i][j]按照*p(i*4+j)操作,仅*p无此功能,要手工转换

此外还有 p[i][j]等价于*a(i*4+j)等价于a[(int)((i*4+j)/3)][(i*4+j)%3]
第4个回答  2009-01-06
其实我也不大明白……闲大了……回个……
相似回答