C语言中“二维数组和数组元素的地址”的为问题。

若先给出以下定义:
int *p,a[3],[4];
则赋值语句 p=a;是合法的语句吗?为什么?
注:二维数组名应该理解为一个行指针。二维数组名同样是一个存放地址常量的指针,其值为二维数组中第一个元素的地址。

1 你代码有错。
int *p,a[3],[4]; //[3]后面怎么有逗号呢?
//改为:
int *p,a[3][4];

2 p=a;不合法。因为类型不匹配。正确的写法如下:
int (*p)[4],a[3][4];
p=a; //上一行定义的p与a的类型才一致。追问

a[0] a[0][0] a[0][1] a[0][2] a[0][3]
a[1] a[1][0] a[1][1] a[1][2] a[1][3]
a[2] a[2][0] a[2][1] a[2][2] a[2][3]
则a[0]的地址就是a[0][0]的地址,a[0]是“存在”的且是“指针”且a[0]自己的地址“并不是”a[0][0]的地址,a,a[0]与a[0][0]是占用着3个不同地址的存储单元且a[0]内部装着的是a[0][0]的地址。
a的值与a[0]相同,只是a包含a[0],a[1],a[2]。而a[0]包含a[0][0] ~ a[0][3],这样理解对么?

追答

不全对。a的值与a[0]相同,但类型不同。a[0]的类型为int *,是整型指针;a的类型为int (*)[4],是行指针,指向一行有四个整型元素的指针。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-08-10
是吧!这不就是把数组a的首地址赋给了定义的地址p嘛!这时p和a的作用基本相同。追问

你错啦。接着继续想想。你说的与标准答案不同噢。

追答

o 惭愧啊

第2个回答  2011-08-10
不合法,因为a是2维数组,p是一级指针。p=a[0]是合法的。追问

“a是二维数组的行指针”这个是书中说的。其内部装着a[0][0]的地址。

追答

是啊,比如说a[0],它其实就是指向二维数组第一行的指针了,本身就是一个指针。那么a就是指向a[0]的指针,也就是指向指针的指针,所以是二维的。而p只是一维的整形指针,如果用p=a,则p指向的内容就会被理解成int类型,但是p本来应该指向的是行地址,所以就类型不匹配了。

追问

a[0] a[0][0] a[0][1] a[0][2] a[0][3]
a[1] a[1][0] a[1][1] a[1][2] a[1][3]
a[2] a[2][0] a[2][1] a[2][2] a[2][3]
则a[0]的地址就是a[0][0]的地址,a[0]是“存在”的且是“指针”且a[0]自己的地址“并不是”a[0][0]的地址,a,a[0]与a[0][0]是占用着3个不同地址的存储单元且a[0]内部装着的是a[0][0]的地址。
a的值与a[0]相同,只是a包含a[0],a[1],a[2]。而a[0]包含a[0][0] ~ a[0][3],这样理解对么?

追答

完全正确。

第3个回答  2011-08-10
可以像这样用,但是要注意转换类型。
int *p,a[3][4];
p=(int *)a;
如果你学过汇编,明白内存寻址方式就好理解了。
其实C语言中并没有真正的二维数组,所谓的二维数组是通过宏定义来实现,把一维数组映射为二维数组。a[3][4]实际上是a[12];都是内存中分配12*sizeof(int)大小的连续内存,a就是其首地址。
a[i][j]等价于a[i*4+j]等价于*(*(a+i)+j);
虽然编译器中类型不同,但它们数据结构上是完全相同的,可以通过显示转换来访问。
例子如下:
#include <stdlib.h>
#include<stdio.h>
int main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *p;
int j;
p=(int *)a;
for(j=0;j<12;j++)
{
printf("%d\t",p[j]);
}
return 0;
}
相似回答