概念
- 一维数组的集合
- 二维数组在内存中的存放
- 按行存放,先顺序存放第一行的元素,再存放第二行的元素
- 二位数组元素的引用
二维数组的初始化
- 二维数组的完整初始化
- 将所有数据写在一个花括号内,按数组的排列顺序对各元素赋初值
- 对部分元素赋初值,其余的元素自动置0
//完整初始化
int[2][2] = {{0,1},{2,1}};
//完整初始化,按照数组排列顺序赋值
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
//部分初始化。其余元素置0
int a[3][4]={1,2,3}; //初始化部分值,按照连续内存逐一赋值 int a[3][0] == 0
int a[3][4]={{1},{2},{3}}; //每个大括号都是int [3]的子数组(一行) int a[3][0] == 3
int a[3][4]={0};
多维数组的总结
- 数组的名字代表首元素的地址
- 数组的名字代表最大个元素类型的首地址
- 二维数组由多个一维数组组成,对于二维数组,每个最大元素类型就是里面的每一个一维数组
- 地址的加减实际上是地址的偏移
- &取地址符:
- 如果后面跟的是变量,代表获取该变量所在的内存空间的地址
- 如果后面跟的是地址,代表相对的扩大地址范围的一倍
- *解引用符:
- 代表缩小地址范围的一倍
- 当缩小到不能再缩小的时,就是取地址里面的数据(此时相当于一个变量名)
- 万能公式:
- *(标识符+偏移量) 《==》 标识符[偏移量]
- *(arr + 1) <---------> arr[1]
- 对于解引用符,例如有一个数组int arr [3] = {1,2,3}
- 此时*(arr + 1) 代表解引用,由于arr + 1在数组中已经是最小地址范围,所以会直接取到地址内部的数据2
- 即*(arr +1) == arr[1] == 变量名
- 若有一个数组 int arr4[4][3] = {1, 2, 3, 4};
- arr4 表示首元素(int [3] 子数组)的地址
- arr4[0] 表示 *arr4 地址范围缩小一级表示子数组内部首元素(int)的地址
- arr4[0][0] 表示 **arr4 首子数组中首个子元素int的值
// "nihao" 是一个字符串常量,返回首字母地址, 需要char类型地址变量(char *)存储其地址
char *str1 = "nihao";
char str_arr[] = "NIHAO";
char *str2 = str_arr;
printf("%s \n", str1);
printf("%c \n", *(str1 + 2));
printf("%c \n", str1[2]);
// str1指向的是字符串常量不可修改
// str1[2] = 'H'; // 段错误
printf("%s \n", str2);
printf("%c \n", str2[2]);
str2[2] = 'h';
printf("%s \n", str2);
// 一维数组存字符串常量首字母地址
char *arr[3] = {"hello", "world", "aaa"};
// arr数组长度为3 其内部存储的是三个字符串常量的首字母地址
printf("%ld \n", sizeof(arr));
printf("%c \n", *(arr[0] + 1));
printf("%c \n", arr[0][1]);
printf("%c \n", arr[1][2]);
// printf("%d \n", arr[2][4]); // 错误越界, 随机数
// arr[0][1] = 'E'; // 段错误
char arr1[3][6] = {"hello", "world", "aaa"};
printf("%ld \n", sizeof(arr1));
printf("%s \n", arr1[0]);
printf("%c \n", arr1[0][1]);
printf("%d \n", arr1[2][4]); // 正确
// 此处的E是给数据段赋值,不发生错误
arr1[0][1] = 'E';
printf("%s \n", arr1[0]);
Comments NOTHING