C语⾔⼆维数组和指针
⼆维数组可以看成是元素为⼀维数组的数组,假设有⼀个三⾏四列的⼆维数组a,它定义为:
int a[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
a 是⼆维数组名。a 数组包含 3 ⾏,即 3 个⾏元素:a[0],a[1],a[2]。每个⾏元素都可以看成含有 4 个元素的⼀维数组。⽽且 C 语⾔规定,a[0]、a[1]、a[2]分别是这三个⼀维数组的数组名。
a[0]、a[1]、a[2] 既然是⼀维数组名,⼀维数组的数组名表⽰的就是数组第⼀个元素的地址,所以
a[0] 表⽰的就是元素 a[0][0] 的地址,即 a[0]==&a[0][0];
a[1] 表⽰的就是元素 a[1][0] 的地址,即 a[1]==&a[1][0];
a[2] 表⽰的就是元素 a[2][0] 的地址,即 a[2]==&a[2][0]。
所以⼆维数组a[M][N]中,a[i]表⽰的就是元素a[i][0]的地址
a[i] == &a[i][0]
a[0]、a[1]、a[2]、…、a[M–1] 分别表⽰⼆维数组 a[M][N] 第 0 ⾏、第 1 ⾏、第 2 ⾏、…、第 M–1 ⾏各⼀维数组的⾸地址,那么同样的道理,
a[0]+1 就表⽰元素 a[0][1] 的地址,
a[0]+2 就表⽰元素 a[0][2] 的地址,
a[1]+1 就表⽰元素 a[1][1] 的地址,
a[1]+2 就表⽰元素 a[1][2] 的地址
a[i]+j 就表⽰ a[i][j] 的地址
a[i]+j == &a[i][j]
&a[i][0]+j == &a[i][j]
c语言二维数组表示方法在⼀维数组中 a[i] 和 *(a+i) 等价
这个关系在⼆维数组中同样适⽤,⼆维数组 a[M][N] 就是有 M 个元素 a[0]、a[1]、…、a[M–1] 的⼀维数组。
*(a+i)+j == &a[i][j]
a[i]+j 和 *(a+i)+j 等价,都表⽰元素 a[i][j] 的地址。
⼆维数组的⾸地址和数组名
⼆维数组 a[M][N] 的数组名 a 表⽰的是谁的地址?”
在⼀维数组中,数组名表⽰的是数组第⼀个元素的地址,那么⼆维数组呢? a 表⽰的是元素 a[0][0] 的地址吗?不是!我们说过,⼆维数组就是⼀维数组,⼆维数组 a[3][4] 就是有三个元素 a[0]、a[1]、a[2]
的⼀维数组,所以数组 a 的第⼀个元素不是 a[0][0],⽽是 a[0],所以数组名 a 表⽰的不是元素 a[0][0] 的地址,⽽是 a[0] 的地址,即:
a == &a[0]
⽽ a[0] ⼜是 a[0][0] 的地址,即:
a[0] == &a[0][0]
所以⼆维数组名 a 和元素 a[0][0] 的关系是:
a == &(&a[0][0])
⼆维数组名 a 是地址的地址,必须两次取值才可以取出数组中存储的数据。对于⼆维数组 a[M][N],数组名 a 的类型为 int(*)[N],所以如果定义了⼀个指针变量 p:int *p;
希望这个指针变量指向⼆维数组 a,那么不能把 a 赋给 p,因为它们的类型不⼀样。要么把 &a[0][0] 赋给 p,要么把 a[0] 赋给 p,要么把 *a 赋给 p。前两个好理解,可为什么可以把 *a 赋给 p?因为 a==&(&a[0][0]),所以 a==(&(&a[0][0]))==&a[0][0]。
除此之外你也可以把指针变量 p 定义成 int(*)[N] 型,这时就可以把 a 赋给 p,⽽且⽤这种⽅法的⼈还⽐较多,但我不喜欢,因为我觉得这样定义看起来很别扭。
# include<stdio.h>
int main(void)
{
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int i, j;
int(*p)[4]= a;//记住这种定义格式
for(i=0; i<3;++i)
{
for(j=0; j<4;++j)
{
printf("%-2d\x20",*(*(p+i)+j));/*%-2d中, '-'表⽰左对齐, 如果不写'-'则默认表⽰右对齐;2表⽰这个元素输出时占两个空格的空间*/
}
printf("\n");
}
return0;
}
# include<stdio.h>
int main(void)
{
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int i, j;
for(i=0; i<3;++i)
{
for(j=0; j<4;++j)
{
printf("%#X\x20",&a[i][j]);
}
printf("\n");
}
return0;
}
输出结果是:
0X18FF18 0X18FF1C 0X18FF20 0X18FF24
0X18FF28 0X18FF2C 0X18FF30 0X18FF34
0X18FF38 0X18FF3C 0X18FF40 0X18FF44
我们看到地址都是连续的。所以对于数组 a[3][4],如果把 &a[0][0] 赋给指针变量 p 的话,那么:
p == &a[0][0]; p + 1 == &a[0][1]; p + 2 == &a[0][2]; p + 3 == &a[0][3];
p + 4 == &a[1][0]; p + 5 == &a[1][1]; p + 6 == &a[1][2]; p + 7 == &a[1][3];
p + 8 == &a[2][0]; p + 9 == &a[2][1]; p + 10 == &a[2][2]; p + 10 == &a[2][3];
# include<stdio.h>
int main(void)
{
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int i, j;
int*p =&a[0][0];//把a[0][0]的地址赋给指针变量p for(i=0; i<3;++i)
{
for(j=0; j<4;++j)
{
printf("%-2d\x20",*(p+i*4+j));
}
printf("\n");
}
return0;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论