一、定义形式

int buf[m][n][z];

int buf[3][2][2];

二、内存结构

三维数组的内存结构,以int buf[3][2][2]为例,也是一片的连续空间

第0元素:二维数组
buf[0][0][0]  buf[0][0][1]  第0元素:一维数组
buf[0][1][0]  buf[0][1][1]  第1元素:一维数组

第1元素:二维数组
buf[1][0][0]  buf[1][0][1]  第0元素:一维数组
buf[1][1][0]  buf[1][1][1]  第1元素:一维数组

第2元素:二维数组
buf[2][0][0]  buf[2][0][1]  第0元素:一维数组
buf[2][1][0]  buf[2][1][1]  第1元素:一维数组
  • (1)将三维看成一维,整个三维数组由3个元素组成,每个元素为一个小二维数组
  • (2)将小二维看成一维,每个小二维数组由2个元素组成,每个元素为一个小一维数组
  • (3)每个一维数组由2int元素组成


三、初始化

1. 不初始化

int buf[3][2][2];

在未初始化时,每个元素的内容为多少,视数组在内存中的位置而定

2. 全部初始化为0

int buf[3][2][2] = {};

3. 完全初始化

int buf[3][2][2] =
{
    {{0, 1}, {2, 3}},  //第0个二维数组
    {{4, 5}, {6, 7}},  //第1个二维数组
    {{8, 9}, {10, 11}} //第2个二维数组
};

4. 部分初始化

部分初始化的时候,三维数组里面的每个二维数组,以及二维数组中每个一维数组,都可以做部分初始化,
做部分初始化,一定是顺序的,其他没有初始化的就是0

int buf[3][2][2] = {
    {{0, 1}}, 
    {{4, 5}, {6}},
    {{8, 9}}
}; // 其余值默认为0

5. 个别初始化

int buf[3][2][2] = {[0][1][0]=10, [2][0][1]=9, [1][1][1]=20} // 未初始化的其它元素默认为0

6. 不给定空间的初始化

int buf[][2][2]= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
没有写的数字 = 元素个数/(2*2)

不能整除的话,那就补增元素,直到能整除为止,补增元素的值默认为0
例子中,元素增补到12就能整除分,这个三维分为3*2*2

除了buf[][2][2]这种方式外,buf[3][][2]buf[3][2][]buf[][][2]等写法都是错误的


四、赋值

#include <stdio.h>

int main(void)
{       
    int buf[3][2][2];

    int i=0, j=0, k=0;

    for(i=0; i<3; i++)
    {
        for(j=0; j<2; j++)
        {
            for(k=0; k<2; k++)
            {
                buf[i][j][k] = i*j*k;
            }
        }
    }

    return 0;
}

当然也能使用memcpy函数来实现两个三维数组之间的复制

int buf1[3][2][2] = {{{0, 1}, {2, 2}}, {{4, 5}, {6, 7}}, {{8, 9}, {10, 11}}};
int buf2[3][2][2];

memcpy((void *)buf2, (void *)buf1, sizeof(buf1));

五、数组名含义

int buf[3][2][2];

buf:数组的别名
指代整个数组空间,sizeof(buf)buf此时指代就是整个数组空间

buf:第0个元素的指针
三维数组的第0个元素为一个二维数组,所以buf为第0个二维数组的数组指针,
等价于&buf[0](buf[0]就是三维数组的第0个元素),也就是第0个小二维数组的第一个字节的地址

buf的指针类型
三维数组的每个元素为一个二维数组,buf的指针类型为int (*)[2][2]

buf+1
buf为第0个二维数组的数组指针,buf+1加的是一个二维数组空间的大小,buf+1实际为buf+1*2*2*sizeof(int)
buf+1,就从第0个二维数组第一个字节处,跳到了第1个二维数组的第一个字节处

buf+i
buf+i实际为buf+i*2*2*sizeof(int),就从第0个二维数组第一个字节处,跳转到第i个二维素组的第一个字节处


六、 &buf

buf:第0个元素指针,也就是第0个二维数组的数组指针

&第0个元素的指针  ————————> 数组指针

0个元素所在的数组为整个三维维数组,所以&buf为整个三维数组的数组指针,
指针类型为int (*)[3][2][2]


七、*buf

buf为三维数组第0个元素的指针,即第0个二维数组的数组指针

*数组指针 ————————> 该数组第一个元素的指针

所以*buf为二维数组第0元素的指针,由于二维数组的第0个元素为一个一维数组,
所以*buf为第0个一维数组的数组指针

*buf的指针类型:
每个小的一维数组有2int元素,所以*buf的指针类型为int (*)[2]

*buf 等价于 *(buf+0)

**buf

**buf ———> *(*(buf+0)+0) ———>

*(第0个二维数组的第0个一位数组的数组指针 + 0) ——> 

第0个二维数组的第0个一维数组的第0个元素的指针,指针为int *。

***buf

***buf ————> *(**buf) ————>

*(第0个二维数组的第0个一维数组的第0个元素的指针(int *)) ————> 

第0个二维数组的第0个一维数组的第0个元素的空间

*(*(*(buf+i)+j)+z)

***buf 等价于 *(*(*(buf+0)+0)):第0个二维数组的第0个一维数组的第0个元素的空间

*(*(*(buf+i)+j)+z):为第i个二维数组的第j个一维数组的第z个元素的空间

*(*(*(buf+i)+j)+z) 的等价写法buf[i][j][k]
*(*(buf[i]+j)+k)、*(buf[i][j]+k)等混合写法也是正确的


八、buf[0]、buf[0][1] 等的含义

一维数组例子:

int buf[10];

回想一维数组,buf是一维数组,那么buf[0]指的就是第0个元素空间

buf是第0个元素指针,*bufbuf[0]都是第0个元素空间,所以我们就可以把[]号就看作是一次解引用


三维数组例子:

int buf[3][2][2];

同理,此时buf是三维数组,那么buf[0]指的就是三维数组的第0个元素空间(二维数组)

同理,buf[0][1]指的就是,三维数组的第0个元素空间(二维数组)的第0个元素空间(一维数组)

同理,buf[0][1][1] 指的就是,三维数组的第0个元素空间(二维数组)的第1个元素空间(一维数组)的第1个元素空间(int 型数据)