引言,
一, 二维数组的初始化定义
1.1,初始化
法1;
int a[4][3] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
10 | 11 | 12 |
法2
int a[4][3] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
10 | 11 | 12 |
法3
int a[4][3] = { {1},{4},{7} ,{10};
1 | 0 | 0 |
4 | 0 | 0 |
7 | 0 | 0 |
10 | 0 | 0 |
法4
int a[4][3] = { {},{},{} };
随机数
法5
int a[4][3];
随机数
法6
int a[4][3] = { 0 };//初始化二维数组元素为零
0 0 0
0 0 0
0 0 0
0 0 0
0 | 0 | 0 |
0 | 0 | 0 |
0 | 0 | 0 |
0 | 0 | 0 |
法7
int a[][3] = { {1,2,3 },{4,5,6},{7,8,9} };
这样是对的但是这个二维数组一共有3行3列
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
1.2,错误案例
错误案例
int a[][] = { {1,2,3,4 },{5,6,7,8},{9,10,11,12} };
//二维数组没有下标第二的[]没有下标
其实可以省咯这个
int a[3][] = { {1,2,3 },{4,5,6},{7,8,9} };
这个是不对的,每行的个数不能省咯
#include<stdio.h>
int main()
{
int a[][3] = { {1,2,3 },{4,5,6},{7,8,9} };
for (int i = 0; i<3;i++)
{
for (int j = 0; j < 3; j++)
printf("%d ", a[i][j]);
printf("\n");
}
return 0;
}
1.3,总
二维数组在定义时行数可省略,每行的个数不可省略,注意在代码里小心数组地址越界
二,二维数组-地址
数组名首元素的地址,指针可以存放地址
相当于数组名是指向首元素的指针,对数组名解引
用,就能找到数组首元素
#include<stdio.h>
int main()
{
int a[100] = { 1,2,3 };
printf("%d", *a);
return 0;
}
这个结果就是1
也就是说 *a等价于 &a[0]
那么 a+i 等价于 &a[i]
2.1,数组与函数间的传递
在函数传递变量有两种
1. 形参与是实参
这种传递的区别在于,函数体内对形参进行操作不会影响实参
2. 传地址
用一个指针来接收地址就可以间接在函数体内对地址中的量进行操作
对于数组来说用数组名,代表首元素的地址,
int add(int a[])
这其中我们用a[]来接受数组首元素的地址
在函数传数组中用 函数名,传递首元素地址
所以数组传参数,传的是地址,不是将实参传递给形参
#include<stdio.h>
void gui2(int x[])
{
for (int i = 0; i < 3; i++)
x[i] = 2;
}
int main()
{
int a[3] = { 1,2,3 };
gui2(a);
for (int i = 0; i < 3; i++)
printf("%d ", a[i]);
return 0;
}
这串代码的结果时:2 2 2
这串代码通过gui2()函数将数组a的中的元素修改成2在main()函数里输出数组a就发生了改变,这就是数组传参数传地址,在函数里通过数组的地址对数组中元素进行修改
2.2,二维数组-地址
举个例子
#include<stdio.h>
int main()
{
int a[2][2] = { 0 };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%p\n", &a[i][j]);
}
}
return 0;
}
000000694AB8FCA8---a[0][0]
000000694AB8FCAC--a[0][1]
000000694AB8FCB0--a[1][0]
000000694AB8FCB4--a[1][1]
我们发现 a[0][1]与a[1][0]]的地址相差了4,正好一个整型
也就是说每一行末为元素后跟下一行首元素
那么如果单用一个指针来指向二维数组的话(在 “二维数组 - 指针语法 ”中有解释 )
int *p=a;
000000694AB8FCA8---a[0][0]------p------------p+0*2+0
000000694AB8FCAC--a[0][1]-------p+1--------p+0*2+1
000000694AB8FCB0--a[1][0]-------p+2---------p+1*2+0
000000694AB8FCB4--a[1][1]-------p+3---------p+1*2+1
三,二维数组 - 指针语法
3.1 a[i]+j 代表 &a[i][j]
对于二维数组可以看成几个一维数组构成的
int a[2][2] = { 0 };//定义
//a[0] 这代表二维数组第一行的首元素的地址
//a[0] 可以看成一个指针,指向二维数组第一行首元素的地址
那么:a[0]+1就是a[0][1]的地址
那末:a[1]+1就是a[1][1]的地址
3.2 a+i 代表 &a[i][0]
那这个指针a + 1指向谁的地址呢,其实时a[1][0]的地址
对于二维数组的数组名,对数组名加1,指向的是下一行的首元素的地址
3.3 *(a+i)+j 代表 &a[i][j]
由前面对一维数组int a[3];
a+1等价与a[1]
那么二维数组里:(*(a+1)+1)等价于a[1][1]
源码
#include<stdio.h>
int main()
{
int a[2][2];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%p\n", &a[i][j]);
}
}
printf("%p\n", (*(a + 1) + 1));
//(*(a+1)+1)就是&a[1][1]
return 0;
}
(*(a+1)+1)就是&a[1][1]
3.4 (p+i*行数+j) 代表 &a[i][j]
咳咳,如果单用一个指针变量来指向一个二维数组的话
(p+i*行数+j)代表&a[i][j]
3.5 总结
a[i]+j | &a[i][j] | |
a+i | &a[i][0] | |
*(a+i)+j | &a[i][j] | |
a+i*行数+j | &a[i][j] | |
四,数组指针
4.1 数组指针是什么
数组指针是一个指针,这个指针指向一个数组
int (*p)[3]
对于 * [] 这两个由于[]得由优先级比*大所以要用括号,括住*p防止p先与[]结合
理解
这串代码这样读 *p是一个指针 他指向一个数组 数组得元素个数为3 这个数组的数据类型是int(整形)
即数组指针是指针这个指针是一个指向数组的指针,而指针数组是一个数组,一个存放指针的数组
对于一维数组的话
int a[3]={1,2,3};
int (*p)[3]=a;
则 p=&a[0];p+1=&a[1];p+2=&a[2]
如果是一个二维数组的话
int a[3][3]={1,2,3};
int (*p)[3]=a;
则 p=a[0][0] p+1=a[1][0] p+2=a[2][0]
五,指针数组
指针数组是一个数组,这个数组存放的是指针,
int *p[3];
这是一个数组,数组里的元素是指针,指针指向类型是int
数组指针是指针,指针指向数组,
指针数组是数组,数组的元素是指针