二维数组

接下来我们同样从以下几个方面来学习一维数组

0x00 数组定义

二维数组声明定义的格式是:type ArrayName [LineNum][RowNum];

  • type:数组元素的数据类型
  • ArrayName:数组的数组名
  • LineNum:一维数组的个数,可以形象的理解为行数
  • RowNum:一维数组元素的个数,可以形象的理解为列数

例如:int a[2][10];定义了一个名为a的二维数组,该数组有2个一维数组a[0]和a[1],每个一维数组有10个成员 每个成员都是int类型,这些成员是连续存放的,逻辑上可以理解为2行10列。a[0]/a[1]分别是两个一维数组的数组名,也是两个数组首元素的地址

  • 该定义开辟了sizeof(int)*10*2=80字节的连续内存空间,依次连续存放a[0][0]~a[0][9]a[1][0]~a[1][9]20个元素
  • 二维数组名a、一维数组名a[0]a[1]是一个常量,不能当做变量被赋值
  • 此时该数组并没有被初始化,每个元素的值是随机的

注意int a[2][10];

  • a[0]代表第一行数组的首元素地址,即a[0][0]的地址,a[0]+1表示a[0][1]的地址
  • a[1]代表第二行数组的首元素地址,即a[1][0]的地址,a[1]+1表示a[1][1]的地址
  • a代表第一行数组的首地址,即a[0]的地址,a+1表示a[1]的地址
  • &a代表整个二维数组的地址,&a+1表示跳过了整个二维数组
  • a+i表示第i行数组的首地址,相当于一维数组名使用&取地址
  • *(a+i)表示第i行数组首元素的地址,相当于一维数组名
  • *(a+i)+j表示第i行第j列元素的地址,等价于&a[i][j]
  • *(*(a+i)+j)表示第i行第j列元素的值,等价于a[i][i]

0x01 数组初始化

当定义一个数组时只是分配了相应的内存空间,内存空间存储的依然是之前的随机值,此时需要通过初始化存放我们想要存储的数据;数组初始化的方式有:

  • int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};:初始化了3个一维数组a[0]~a[2]
  • int a[3][4] = {{1,2,3,4},{5,6,7,8}};:初始化了3个一维数组a[0]~a[2],a[2]所有元素都是0
  • int a[3][4] = { 0 };:初始化了3个一维数组a[0]~a[2],所有一维数组的所有元素都是0
  • int a[][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{0}};:初始化了4个一维数组a[0]~a[3]
  • char a[][10] = {"my","name","is","anony"};:初始化了4个一维数组a[0]~a[3],使用int a[][]会直接报语法错误

0x02 数组访问

二维数组同样是通过索引下标的方式来访问元素的,以下demo代码就是访问二维数组每个元素然后打印输出

#include <stdio.h>
int main(){
        int i, j;
        int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
        int line_index = sizeof(a)/sizeof(a[0]);
        int row_index = sizeof(a[0])/sizeof(a[0][0]);
        for(i=0; i < line_index; i++) {
                for(j=0; j < row_index; j++)
                {
                        printf("%d\n",a[i][j]);
                }
        }
        return 0;
}

上述demo代码中:

  • sizeof(a)表示二维数组a在内存中占用大小
  • sizeof(a[0])表示一维数组a[0]在内存中占用大小[即每个一维数组在内存中占用大小]
  • sizeof(a[0][0])表示一维数组a[0]首元素在内存中占用大小[即每个元素在内存中占用大小]
  • sizeof(a)/sizeof(a[0])表示一维数组的个数
  • sizeof(a[0])/sizeof(a[0][0])表示一维数组数组元素的个数

0x03 数组应用

冒泡排序

算法思路

  • 先将二维数组放到一个一维数组中

  • 然后对一维数组进行冒泡排序

    • 第一次遍历整个数组n个元素,通过相邻值比较将最大值放到最右边
    • 第二次遍历剩下的n-1个元素,通过相邻值比较将最大值放到最右边
    • 依次循环遍历,直到遍历最后1个元素
  • 最后将一维数组重新放回二维数组中

使用技巧

  • 可以使用二级指针指向二维数组
  • 可以使用一级数组指针指向二维数组
  • 不能使用二级指针做形参来接收二维数组【因为步长不一样】
  • 可以使用一级数组指针做形参来接收二维数组【步长可以保持一致】
  • 可以使用二维数组做形参类接收二维数组【步长可以保持一致】