由于 int 类型和指针的大小相同,都是4字节,所以会产生理解误导;故尽量选择其他大小的变量,该例使用的是2字节的short
#include<stdio.h>
#include<stdlib.h>#define N 5
int func1(short a[N][N])
{
int i,j;
for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}return 0;
}/*重点:一个二维数组a[5][4],数组名a代表他的一级成员取地址,详情见PS
* 故a+1的地址向前前进2个字节,遍历其实就是对一个连续内存的逐个遍历
*/
int func2(short *a, int height, int width)
{
int i=0,j=0;
printf("_a: %p\n", a);
printf("_a+1 :%p\n", a+1);
printf("_a+3 :%p\n", a+3);for(i=0; i<height; i++)
{
for(j=0; j<width; j++)
{
printf("%4d", *(a+i*height+j));
//printf("%4d", );
}
printf("\n");
}
}
/*重点:一个二维数组a[5][4],数组名a代表他的一级成员取地址,详情见PS
* 单纯传一个二维数组的变量名,传的是一个数组指针,该数组是一个一级成员的地址
*/
int func3(short (*a)[N],int height, int width)
{
int i=0,j=0;
printf("_a: %p\n", a); // 0xbfbd07d6
printf("_a+1: %p\n", a+1); // 0xbfbd07e0
printf("_a+2: %p\n", a+2); // 0xbfbd07ea
printf("_a+3: %p\n", a+3); // 0xbfbd07f4printf("_(*(a+1)+1): %p\n", *(a+1)+1); // 0xbfbd07e2
printf("_(*(a+1)+2): %p\n", *(a+1)+2); // 0xbfbd07e4
for(i=0; i<height; i++)
{
for(j=0; j<width; j++)
{
printf("%4d", *(*(a+i)+j));
}
printf("\n");
}
}int allAndOne(short a[N][N])
{
int i,j;
for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
a[i][j]++;
}
}
}
int main()
{
int i,j = 0;
short a[N][N] = {
{1,2,3,4,5},
{6,7,8,9,10},
{11,12,13,14,15},
{16,17,18,19,20},
{21,22,23,24,25}
};
printf("===================original array=================\n");
for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
printf("\nsizeof(a): %d\n", sizeof(a));扫描二维码关注公众号,回复: 5926516 查看本文章printf("===================func1 array=================\n");
func1(a);
printf("===================func2 array=================\n");
func2(*a,N,N);
printf("===================func3 array=================\n");
func3(a,N,N);
printf("===================out paramter=================\n");
allAndOne(a);
func1(a);
}
运行结果如下:
===================original array=================
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25sizeof(a): 50
===================func1 array=================
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
===================func2 array=================
_a: 0xbff53cf6
_a+1 :0xbff53cf8
_a+3 :0xbff53cfc
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
===================func3 array=================
_a: 0xbff53cf6
_a+1: 0xbff53d00
_a+2: 0xbff53d0a
_a+3: 0xbff53d14
_(*(a+1)+1): 0xbff53d02
_(*(a+1)+2): 0xbff53d04
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
===================out paramter=================
2 3 4 5 6
7 8 9 10 11
12 13 14 15 16
17 18 19 20 21
22 23 24 25 26
下面从一维数组说起:(定义:int a[4])
(1)一维数组名a是个地址,地址类型为:int *
(2)一维数组名取地址&a是个地址,地址类型同:int (*p)[4], 也即&a指向含4个int元素的一维数组
再看二维数组b[3][4],这个二维数组也可以可以看成一个含3个成员的一维数组,每一个成员含有4个int元素,依次,仿照一维数组的结论,有:
(1)b[0]是个一维数组名,也是个地址,地址类型为:int *
(2)&b[0]是个地址,地址类型同:int (*p)[4], 也即&b[0]指向含4个int元素的一维数组
更进一步:
(3)b是个地址,地址类型同:int (*p)[4],也即b指向含4个int元素的一维数组
(4)&b是个地址,地址类型同:int (*p)[3][4],也即&b指向含3x4个int元素的2维数组
注意:尤其注意上面的(3),这条结论指出了:二维数组名实际上是一维数组的地址!
总结:
① 数组名,是指向它的第一个一级成员的指针
② 数组名取地址,是指向整个数组的指针
PS:所谓一级成员,举个例子,int a[5],那么数组a的一级成员就是int型变量;int b[2][5],数组b的一级成员是int [5]的一维数组
补充一个memcpy复制二维数组的demo:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>#define H 3
#define W 5int func1(short a[H][W])
{
int i,j;
for(i=0; i<H; i++)
{
for(j=0; j<W; j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
return 0;
}
int main()
{
int i,j;
short a[H][W] = {0};
short b[H][W] = {0};
for(i=0; i<H; i++)
{
for(j=0; j<W; j++)
{
a[i][j] = i+j;
}
}printf("===========Array A================\n");
func1(a);
printf("===========Array B================\n");
printf("sizeof(a): %d\n",sizeof(a));
memcpy(b, a, sizeof(a));
func1(b);
return 0;
}
运行结果如下:
===========Array A================
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
===========Array B================
sizeof(a): 30
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6