C语言----指针与二维数组(高阶篇三十一)
数组的特殊情况
※数组在定义时可以省略下标:
int ai[]={1,2,3};
编译器会自动算出此数组在初始化时有3个元素,自动定义成int ai[3]={1,2,3};
这种方法经常用在字符串上:
char str[]={“string”};
※二维数组初始化时,只有第一维下标可以省略:
int ai[][3]={{1,2,3},{4,5,6}};
※也可以用一维数组的形式初始化二维数组:
int ai[][3]={1,2,3,4,5,6};
缺胳膊少腿也行:
int ai[][3]={1,2,3,4};
元素ai[1][1]和ai[1][2]会自动初始化为0
※无论多少维数组,它的内存都连成一片,我们可以用通过指针的移动来指向数组中的任何一个元素。
int ai[][3]={1,2,3,4,5,6};
int *pi=&ai[0][0];
pi+=3;
这时pi指向ai[1][0];
注意以下写法都是错误的:
※int ai[][3]={{1,2,3}{4,5,6}};
少了中间的逗号
※int ai[][3]={{1,2,3},{}};
不能用空花括号初始化,一维数组也一样
※int ai[0];
不能定义只有0个元素的数组
※int ai[3][]={{1,2,3},{4,5,6}};
除第一维下标外,其它维的下标都不能省略
二维数组与指针
在学二维数组与指针之前,我们先回顾下一维数组与指针的关系。
a[3]等价于*(a+3)
a[0]等价于*(a+0)等价于*a
二维数组可当成是“数组的数组”,假设二维数组定义如下:
int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}
a是个数组名,包含3个元素:a[0],a[1],a[2],每个元素又是一个数组,包含4个元素a[0][0],a[0][1],a[0][2],a[0][3]。
从一维数组的知识得知:a[2]相当于*(a+2),但是它只能取到下一维数组的地址,即&a[2][0]。那么如何取到a[1][2]的内容呢?用如下方法:
*(*(a+1)+2)
它等价于
a[1][2]
※一般在没有&影响的情况下,n维数组中有n个*就会取到数据,小于n个*,只能取到地址。
通过以上表达式,我们可以推出另外几个表达式:
a[0][1]等价于*(*(a+0)+1)等价于*(*a+1)
a[1][0]等价于*(*(a+1)+0)等价于**(a+1)
a[0][0]等价于*(*(a+0)+0)等价于**(a+0)
题目讲解:
已知数组int x[5][4]={0};中x的地址为0x0AFD0100,求**(x+3)+2、*x+3、*(*(x+3)+2)的地址或值。
参考答案:2 0x0AFD010C 0
说明: 一、**(x+3)+2相当于*(*(x+3)+0)+2相当于x[3][0]+2=2
二、*x+3 相当于*(x+0)+3相当于x[0]+3相当于x[0][3]的地址&x[0][3],等于0x0AFD0100+3*4等于0x0AFD0100+C=0x0AFD010C。
三、*(*(x+3)+2)相当于x[3][2]=0
程序1
二维数组与指针的关系
// 31-1二维数组与指针的关系.c #include <stdio.h> main() { int a[2][3] = { 1,3,5,7,9,11 }; //定义二维数组 printf("%d \n", &a); printf("%d,%d \n", a, *a); printf("%d,%d \n", a[0], *(a + 0)); printf("%d,%d \n", &a[0], &a[0][0]); printf("%d,%d \n", a[1], *(a + 1)); printf("%d,%d \n", &a[1], a + 1); printf("%d,%d \n", &a[1][2], *(*(a + 1) + 2)); printf("%d,%d \n", a[1][0], *(*(a + 1) + 0)); }
测试结果:
多维数组
多维数组地址换算
※上图分析是通过元素个数来是计算地址:例子
求 a[1][2][1] 的地址:
a[1][2][1] = 2116 + (1 * 3 * 2 + 2 *2 + 1) *4 = 2160
※内存是线性结构,数组维数再多,也要通过公式转换为线性地址将数据存储在内存中。