一、下标方式访问

int buf[2][3] = {{0, 1, 2}, {3, 4, 5}};

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

二、指针方式访问

[]访问方式的本质也是通过指针来访问,现在来看一下,如何通过指针方式来访问二维数组的每个元素的

int buf[2][3] = {{0, 1, 2}, {3, 4, 5}};

int i=0, j=0; 

for(i=0; i<2; i++)
{
    for(j=0; j<2; j++)
    {
        *(*(buf+i)+j)= i*j;
    }
}

*(*(buf+i)+j)是如何访问到第i个一维数组的第j个元素的

第一步:buf+i,得到第i个一维数组的数组指针
第二步:*(buf+i),进行强制转换,得到第i个一维数组的第0个元素的指针
第三步:*(buf+i)+j, 得到第i个一维数组的第j个元素的指针
第四步:*(*(buf+i)+j),解引用第j个元素的指针,得到第j个元素的空间


三、普通传参方式

#include <stdio.h>

void fun(int m, int n, int (*p)[3])  //或则int (*p)[n]
{
    int i=0, j=0;

    for(i=0; i<2; i++)
    {
        for(j=0; j<2; j++)
        {
            printf("%d \n", *(*(p+i)+j));
        }
    }

    printf("\n");
}

int main(void)
{
    int buf[2][3] = {{0, 1, 2}, {3, 4, 5}};

    fun(2, 3, buf); //int (*)[3]

    return 0;
}

fun(2, 3, buf)buf为第0个一维数组的数组指针,每个一维数组有3个元素,
因此类型为int (*)[3],所以形参的类型也为int (*)[3]

传参时,如果不知道形参怎么写,那就搞清楚实参类型,然后你就知道形参应该怎么写

3不能省略,也不能写成2/4/5等其它值,否则在访问每个小一维数组时,就不能准确找到每个小一维数组
n会被传参为3,所以int (*)[3]3也可以改为n

二维数组形参的等价写法:

void fun(int m, int n, int (*p)[n]) // 一维数组传参中讲过,*p 可替换为 p[]
{
}

等价于

void fun(int m, int n, int p[][n])
{
}

int p[][n]也可以写成int p[m][n],第一个[]中有没有数字都无所谓,但是n必须要有


四、指针传参方式

1. 传参 *buf

buf为第0个一维数组的指针(即:一维数组指针),所以*buf强制转后,变成第0个一维数组的第0个元素指针地址

*buf为第0个一维数组第0个元素的指针,此时可以将“整个二维数组”看成一个有6个元素的大的一维数组,
*buf为整个大的一维数组的第0个元素的指针,此时完全可以以一维数组的方式来访问二维数组。

#include <stdio.h>

void fun(int m, int n, int *p)
{
    int i=0, j=0;
    for(i=0; i<2*3; i++)
    {
        printf("%d \n", *(p+i));
    }
    printf("\n");
}

int main(void)
{
    int buf[2][3] = {{0, 1, 2}, {3, 4, 5}};

    fun(2, 3, *buf); // 等价于fun((int *)buf)

    return 0;
}

2. 传参 &buf

(1)以三维数组方式来访问二维数组

&buf为整个二维数组的数组指针,&buf的指针类型为int (*)[2][3]23不能省略,
后面介绍三维数组时,就知道为什么不能省略了

#include <stdio.h>

void fun(int m, int n, int (*buf)[m][n]) //m和n不能省略
{
    /* 方式1:以二维数组方式访问 */
    int (*p)[n] = *buf; //等价于int (*p)[n] = (int (*)[n])buf 

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

    for(i=0; i<m; i++)
    {
        for(j=0; j<n; j++)
        {
            printf("%d \n", *(*(p+i)+j));
        }
        printf("\n");
    }

    /* 方式2:以三维数组访问
           * 三维数组是由二维数组构成的,将二维数看成是一个只有一个二维数组的三维数组。
    */
    for(i=0; i<1; i++)
    {
        for(j=0; j<m; j++)
        {
            for(k=0; k<n; k++)
            {
                // 因为buf是数组指针,数组指针加i,相当于就是加的是一个完整的数组内存空间
                // 这里i等于0,可以看出是三维数组的第0个元素,这三维数组里面的只有一个二维数组
                printf("%d \n", *(*(*(buf+i)+j)+k)); //buf[i][j][k]
            }
        }
    }
    printf("\n");
}

int main(void)
{
    int buf[2][3] = {{0, 1, 2}, {3, 4, 5}};

    fun(2, 3, &buf); //等价于fun(2, 3, (int (*)[m][n)buf)

    return 0;
}

(2)以二维数组方式来访问一维数组

进行一维数组传参时,也可以传递“数组指针”,然后以二维数组的方式来访问,
此时我们可以将之前讲的“一维数组”看成是只包含一个小一维数组的二维数组

#include <stdio.h>

void fun(int n, int (*buf)[10])
{
    int i=0, j=0;

    /* 访问方式1 */
    int *p = (int *)buf; //等价于int *p = *buf

    for(i=0; i<n; i++){
        printf("%d", *(buf + i)); //buf[i]
    }


    /* 方式2 */
    for(i=0; i<1; i++) //只有要一维数组,所以i只取0值
    {
        for(j=0; j<n; j++) 
        {
            printf("%d", *(*(buf+i)+j)); //buf[i][j]
        }
    }
}

int main(void)
{
    int buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    fun(10, &buf);

    printf("\n");

    return 0;
}