21.指针-指针和数组-指针和二维数组
21.1 知识点
指针和二维数组的关系
二维数组在内存中也是连续存储的,因此我们只要利用指针获取到二维数组一开始的位置,就可以通过指针的增减获取到二维数组中的所有信息。
建立关系
指针类型需要和二维数组类型一致
int arr[2][4] = {1, 2, 3, 4, 5, 6, 7, 8};
按元素建立关系
int* p = &arr[0][0]; // 得到的是第一行第一列的元素地址
int* ptr = arr[0]; // 得到的是第一行的地址 = 第一行第一列的元素地址
数组指针按行数组建立关系
利用数组指针,获取二维数组中一行的一维数组起始地址。数组指针是一个指向整个数组的指针,本质上是一个指针,指向一个包含n个元素的数组。
数组指针定义规则:
变量类型 (*指针名)[元素个数]
int (*p2)[4] = arr;
- 数组指针每次使用
++
或--
偏移是偏移一行的。例如,int类型数组包含四个元素,那么一次偏移为 4x4=16个字节。
利用指针获取二维数组元素
由于二维数组的存储序列也是连续的,因此利用指针增减也可以获取到所有元素。
按元素获取的指针
cout << "******按元素获取的指针********" << endl;
cout << *p << endl; // 1
cout << *(p + 1) << endl; // 2
cout << *++p << endl; // 2
cout << *--p << endl; // 1
cout << *(p += 3) << endl; // 4
cout << *++p << endl; // 5
cout << *(p + 3) << endl; // 8
注意: 要在范围内访问 0 <= i < 行 * 列
之间,不要越界。
用数组指针获取元素
p2
是什么?
类型是:数组指针 int (*)[4]
指向的内容:指向二维数组中的第一个一维数组
每次增减 偏移位置为:元素字节数 * 容量
cout << "p2: " << p2 << endl;//数组指针 第一行数组首地址
cout << "p2 + 1: " << p2 + 1 << endl;//数组指针 第二行数组首地址 偏移元素*容量 16个字节
cout << "p2 的类型: " << typeid(p2).name() << endl; // int (* __ptr64)[4]
*p2
是什么?
类型是:指向一维数组指针 int*
指向的内容:指向二维数组中的第一个一维数组中的第一个元素
每次增减 偏移位置为:元素字节数
cout << "*p2: " << *p2 << endl;//指针 指向二维数组中的第一个一维数组中的第一个元素
cout << "*p2 + 1: " << *p2 + 1 << endl;//指针 指向二维数组中的第一个一维数组中的第二个元素 偏移元素的 4个字节
cout << "*p2 的类型: " << typeid(*p2).name() << endl; // int [4] *p2 的解引用操作返回的是数组本身,所以它的类型是 int[4]。
以下是几种获取元素的方法:
对数组指针偏移一个数组长度后去取值
//对数组int (*)[4]指针类型变量 使用*取值 取出来的是类型是int*的指针
cout << "*(p2): " << *(p2) << endl;//指针 第一行数组首地址 也是第以行数组首元素的地址
cout << "*(p2 + 1) : " << *(p2 + 1) << endl;//指针 第二行数组首地址 也是第二行数组首元素的地址
cout << "**(p2 + 1) : " << **(p2 + 1) << endl;//5 取值
对数组指针先偏移一个数组长度后得到指针,再偏移元素个数,再去取值
//(p2 + 1)得到的还是数组指针
//*(p2 + 1)得到的是指针 指向第二行数组首地址
//在指针的基础上偏移 int偏移一次是4个单位 每次向后拿元素
cout << "*(*(p2 + 1) + 1): " << *(*(p2 + 1) + 1) << endl;//6
cout << "*(*(p2 + 1) + 2): " << *(*(p2 + 1) + 2) << endl;//7
cout << "*(*(p2 + 1) + 3): " << *(*(p2 + 1) + 3) << endl;//8
对数组指针取值得到指针,再偏移元素个数,再去取值
//一维数组第一个元素地址中存储的值 *p2得到指针 指针偏移x个单位还是指针 *指针得到值
cout << **p2 << endl;//1
cout << *(*p2 + 1) << endl;//2 往后移动元素n个字节数
cout << *(*p2 + 2) << endl;//3
cout << *(*p2 + 3) << endl;//4
cout << *(*p2 + 4) << endl;//5
cout << *(*p2 + 5) << endl;//6
cout << *(*p2 + 6) << endl;//7
cout << *(*p2 + 7) << endl;//8
对数组指针取值得到指针,使用 [x]
得到对应数组的元素
//结合数组指针 利用数组思维去获取元素内容
//(*p2)得到的是指针 指向第一行首元素 传入索引得到值
cout << (*p2)[0] << endl;
cout << (*p2)[1] << endl;//2 往后移动元素n个字节数
cout << (*p2)[2] << endl;//3
cout << (*p2)[3] << endl;//4
//(*(p2 + 1)得到的是指针 指向第二行首元素 传入索引也可以得到值
cout << (*(p2 + 1))[0] << endl;//5
cout << (*(p2 + 1))[1] << endl;//6
cout << (*(p2 + 1))[2] << endl;//7
cout << (*(p2 + 1))[3] << endl;//8
数组当做指针变量使用
cout << arr[0][0] << endl; // 1
cout << arr[0] << endl; // 第一个数组的地址
利用行地址来获取元素
先得到行首地址,再通过加减来获取某行某元素。
cout << *arr[0] << endl; // 1
cout << *p2[0] << endl; // 1
cout << *(arr[0] + 1) << endl; // 2
cout << *(p2[0] + 1) << endl; // 2
cout << *(arr[0] + 2) << endl; // 3
cout << *(arr[0] + 3) << endl; // 4
cout << *(arr[0] + 4) << endl; // 5, 但是最好不要这样,逻辑上看是越界了
cout << *arr[1] << endl; // 5
cout << *(arr[1] + 1) << endl; // 6
cout << *(arr[1] + 2) << endl; // 7
cout << *(arr[1] + 3) << endl; // 8
利用二维数组名来获取元素
二维数组名可以理解为一个 int (*)[4]
类型的指针。arr和*arr的区别就像p2 和 *p2 的区别。
cout << arr << endl;//第一行数组地址
cout << *arr << endl;//第一行数组的第一个元素地址 其实和arr一样
对于我们来说,需要知道的是,arr + 1 会按行偏移,偏移后得到的地址是当前行的首地址。arr的使用规则,和数组指针p2使用规则是一样的。
//数组指针
cout << arr + 1 << endl;//第二行数组地址
cout << *(arr + 1) << endl;//第二行数组首元素的地址 其实和arr + 1一样
cout << **(arr + 1) << endl;//5
cout << *(*(arr + 1) + 1) << endl;//6
cout << *(*(arr + 1) + 2) << endl;//7
cout << *(*(arr + 1) + 3) << endl;//8
注意: 数组指针与二维数组名有区别,获取数组容量时,二维数组名占用的是实际字节数,而数组指针占用的内存空间是8个字节。
cout << sizeof(p2) << endl;//8 只要是指针都是8字节
cout << sizeof(arr) << endl;//32 4x8
利用指针遍历数组
int array[2][4] = { 1,2,3,4,
5,6,7,8 };
//按元素 int指针
int* p3 = &array[0][0];//array[0];
//按行 int数组指针
int(*ptr3)[4] = array;
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
{
// 外层循环:遍历二维数组的每一行
// sizeof(array) / sizeof(array[0]) 计算二维数组的行数
// 列
for (int j = 0; j < sizeof(array[0]) / sizeof(int); j++)
{
// 内层循环:遍历当前行中的每一列
// sizeof(array[0]) / sizeof(int) 计算每行中的列数
// 方法 1:直接通过二维数组下标访问
cout << array[i][j] << endl;
// 解释:通过 `array[i][j]` 访问二维数组第 i 行、第 j 列的元素
// 方法 2:通过一维指针 `p3` 访问
cout << *p3++ << endl;
// 解释:`p3` 是指向数组首地址的一维指针,`*p3` 取当前指针位置的值,并自增指针(移动到下一个元素)
// 方法 3:通过指针偏移访问
cout << *(*(ptr3 + i) + j) << endl;
// 解释:`ptr3` 是一个指针,指向二维数组的行指针
// `*(ptr3 + i)` 取第 i 行的行首指针
// `+ j` 是列偏移,`*(...)` 解引用后得到元素值
// 方法 4:通过二维数组指针 `array` 偏移访问
cout << *(*(array + i) + j) << endl;
// 解释:`array` 是二维数组,`array + i` 是第 i 行数组首地址
// `+ j` 是列偏移,`*(...)` 解引用后得到元素值
// 方法 5:通过行指针 `array[i]` 偏移访问
cout << *(array[i] + j) << endl;
// 解释:`array[i]` 是指向第 i 行的行首指针
// `+ j` 是列偏移,`*(...)` 解引用后得到元素值
// 方法 6:通过行指针数组 `ptr3[i]` 偏移访问
cout << *(ptr3[i] + j) << endl;
// 解释:`ptr3[i]` 是指向第 i 行的行首指针
// `+ j` 是列偏移,`*(...)` 解引用后得到元素值
}
}
输出五次 1234
。
总结
- 理解二维数组中,数组指针怎么用,以及
array
和*array
的区别。- array => 数组指针变量。类型是
类型 (*指针名)[列容量]
。指向的是第一行一维数组的首地址(数组为单位去偏移)。 - *array => 对应类型的指针变量。类型是
类型* 指针名
。指向的是第一行一维数组的第一个元素的首地址(元素为单位去偏移)。
- array => 数组指针变量。类型是
21.2 知识点代码
Lesson21_指针_指针和数组_指针和二维数组.cpp
#include <iostream>
using namespace std;
int main()
{
std::cout << "指针和二维数组\n";
#pragma region 知识点一 指针和二维数组的关系
//二维数组在内存中也是连续存储的
//因此我们只要利用指针获取到二维数组一开始的位置
//就可以通过指针的 增减 获取到二维数组中的所有信息
#pragma endregion
#pragma region 知识点二 建立关系
//关键点:
//1.指针类型需要和二维数组类型一致
int arr[2][4] = { 1,2,3,4,
5,6,7,8 };
//2.按元素建立关系
int* p = &arr[0][0];//得到的是第一行第一列的元素地址
int* ptr = arr[0];//得到的是第一行的地址 = 第一行第一列的元素地址
//3.数组指针 按行数组建立关系
//利用数组指针,获取二维数组中一行的一维数组起始地址
//数组指针是一个指向整个数组的指针
//本质上是一个指针,指向一个包含n个元素的数组
//数组指针定义规则:变量类型 (*指针名)[元素个数]
//
//int (*p2)[4] 表示指向包含4个int元素的一维数组的指针
//int:数组中元素的类型
//*p:指针变量
//[4]:表示这个指针指向的数组包含4个int元素
//指向二维数组中第一个一维数组的指针
int(*p2)[4] = arr;
//数组指针每次使用++ -- 偏移是偏移一行的
//例如int类型数组包含四个元素 那么一次偏移4x4=16个字节
#pragma endregion
#pragma region 知识点三 利用指针获取二维数组元素
//由于二维数组的存储序列也是连续的
//因此利用指针增减也可以获取到所有元素
//1.按元素获取的指针
cout << "******按元素获取的指针********" << endl;
cout << *p << endl;//1
cout << *(p + 1) << endl;//2
cout << *++p << endl;//2
cout << *--p << endl;//1
cout << *(p += 3) << endl;//4
cout << *++p << endl;//5
cout << *(p + 3) << endl;//8
//注意:
//要在范围内访问0<= i < 行*列 之间
//不要越界,不要越界,不要越界
//2.用数组指针获取元素
cout << "******用数组指针获取元素********" << endl;
// p2是什么?
// 类型是:数组指针 int (*)[4]
// 指向的内容:指向二维数组中的第一个一维数组
// 每次增减 偏移位置为:元素字节数 * 容量
cout << "p2: " << p2 << endl;//数组指针 第一行数组首地址
cout << "p2 + 1: " << p2 + 1 << endl;//数组指针 第二行数组首地址 偏移元素*容量 16个字节
cout << "p2 的类型: " << typeid(p2).name() << endl; // int (* __ptr64)[4]
// *p2是什么?
// 类型是:指向一维数组指针 int*
// 指向的内容:指向二维数组中的第一个一维数组中的第一个元素
// 每次增减 偏移位置为:元素字节数
cout << "*p2: " << *p2 << endl;//指针 指向二维数组中的第一个一维数组中的第一个元素
cout << "*p2 + 1: " << *p2 + 1 << endl;//指针 指向二维数组中的第一个一维数组中的第二个元素 偏移元素的 4个字节
cout << "*p2 的类型: " << typeid(*p2).name() << endl; // int [4] *p2 的解引用操作返回的是数组本身,所以它的类型是 int[4]。
//以下是几种获取元素方法
//对数组指针 偏移一个数组长度后 去取值
//对数组int (*)[4]指针类型变量 使用*取值 取出来的是类型是int*的指针
cout << "*(p2): " << *(p2) << endl;//指针 第一行数组首地址 也是第以行数组首元素的地址
cout << "*(p2 + 1) : " << *(p2 + 1) << endl;//指针 第二行数组首地址 也是第二行数组首元素的地址
cout << "**(p2 + 1) : " << **(p2 + 1) << endl;//5 取值
//对数组指针 先偏移一个数组长度后 得到指针 再偏移元素个数 再去取值
//(p2 + 1)得到的还是数组指针
//*(p2 + 1)得到的是指针 指向第二行数组首地址
//在指针的基础上偏移 int偏移一次是4个单位 每次向后拿元素
cout << "*(*(p2 + 1) + 1): " << *(*(p2 + 1) + 1) << endl;//6
cout << "*(*(p2 + 1) + 2): " << *(*(p2 + 1) + 2) << endl;//7
cout << "*(*(p2 + 1) + 3): " << *(*(p2 + 1) + 3) << endl;//8
//对数组指针取值得到指针 再偏移元素个数 再去取值
//一维数组第一个元素地址中存储的值 *p2得到指针 指针偏移x个单位还是指针 *指针得到值
cout << **p2 << endl;//1
cout << *(*p2 + 1) << endl;//2 往后移动元素n个字节数
cout << *(*p2 + 2) << endl;//3
cout << *(*p2 + 3) << endl;//4
cout << *(*p2 + 4) << endl;//5
cout << *(*p2 + 5) << endl;//6
cout << *(*p2 + 6) << endl;//7
cout << *(*p2 + 7) << endl;//8
//对数组指针取值得到指针 使用[x] 得到对应数组的元素
//结合数组指针 利用数组思维去获取元素内容
//(*p2)得到的是指针 指向第一行首元素 传入索引得到值
cout << (*p2)[0] << endl;
cout << (*p2)[1] << endl;//2 往后移动元素n个字节数
cout << (*p2)[2] << endl;//3
cout << (*p2)[3] << endl;//4
//(*(p2 + 1)得到的是指针 指向第二行首元素 传入索引也可以得到值
cout << (*(p2 + 1))[0] << endl;//5
cout << (*(p2 + 1))[1] << endl;//6
cout << (*(p2 + 1))[2] << endl;//7
cout << (*(p2 + 1))[3] << endl;//8
#pragma endregion
#pragma region 知识点四 数组当做指针变量使用
cout << "******数组当做指针变量使用*******" << endl;
cout << arr[0][0] << endl;//1
cout << arr[0] << endl;//第一个数组的地址
//1.利用行地址来获取元素
cout << "******利用行地址来获取元素*******" << endl;
// 先得到行首地址,在通过加减来获取某行某元素
cout << *arr[0] << endl;//1
cout << *p2[0] << endl;//1
cout << *(arr[0] + 1) << endl;//2
cout << *(p2[0] + 1) << endl;//2
cout << *(arr[0] + 2) << endl;//3
cout << *(arr[0] + 3) << endl;//4
cout << *(arr[0] + 4) << endl;//5 但是最好不要这样 逻辑上看是越界了
cout << *arr[1] << endl;//5
cout << *(arr[1] + 1) << endl;//6
cout << *(arr[1] + 2) << endl;//7
cout << *(arr[1] + 3) << endl;//8
//2.利用二维数组名来获取元素
cout << "******利用二维数组名来获取元素*******" << endl;
//关键知识:
// 二维数组名 可以理解为一个 int (*)[4] 类型的指针
//arr和*arr的区别
//就像前面讲解的 p2 和 *p2 的区别
cout << arr << endl;//第一行数组地址
cout << *arr << endl;//第一行数组的第一个元素地址 其实和arr一样
//对于我们来说,需要知道的是
//arr + 1 会按行偏移
//偏移后得到的地址是当前行的首地址
//arr的使用规则,和数组指针p2使用规则是一样的
//数组指针
cout << arr + 1 << endl;//第二行数组地址
cout << *(arr + 1) << endl;//第二行数组首元素的地址 其实和arr + 1一样
cout << **(arr + 1) << endl;//5
cout << *(*(arr + 1) + 1) << endl;//6
cout << *(*(arr + 1) + 2) << endl;//7
cout << *(*(arr + 1) + 3) << endl;//8
//二维数组名和数组指针有什么区别?
//他们通过sizeof获取容量时
//二维数组名得到的是实实在在的这个二维数组占用了多少个字节
//数组指针(只要是指针)占用的内存空间是8个字节
cout << sizeof(p2) << endl;//8 只要是指针都是8字节
cout << sizeof(arr) << endl;//32 4x8
#pragma endregion
#pragma region 知识点五 利用指针遍历数组
cout << "遍历二维数组" << endl;
int array[2][4] = { 1,2,3,4,
5,6,7,8 };
//按元素 int指针
int* p3 = &array[0][0];//array[0];
//按行 int数组指针
int(*ptr3)[4] = array;
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
{
// 外层循环:遍历二维数组的每一行
// sizeof(array) / sizeof(array[0]) 计算二维数组的行数
// 列
for (int j = 0; j < sizeof(array[0]) / sizeof(int); j++)
{
// 内层循环:遍历当前行中的每一列
// sizeof(array[0]) / sizeof(int) 计算每行中的列数
// 方法 1:直接通过二维数组下标访问
cout << array[i][j] << endl;
// 解释:通过 `array[i][j]` 访问二维数组第 i 行、第 j 列的元素
// 方法 2:通过一维指针 `p3` 访问
cout << *p3++ << endl;
// 解释:`p3` 是指向数组首地址的一维指针,`*p3` 取当前指针位置的值,并自增指针(移动到下一个元素)
// 方法 3:通过指针偏移访问
cout << *(*(ptr3 + i) + j) << endl;
// 解释:`ptr3` 是一个指针,指向二维数组的行指针
// `*(ptr3 + i)` 取第 i 行的行首指针
// `+ j` 是列偏移,`*(...)` 解引用后得到元素值
// 方法 4:通过二维数组指针 `array` 偏移访问
cout << *(*(array + i) + j) << endl;
// 解释:`array` 是二维数组,`array + i` 是第 i 行数组首地址
// `+ j` 是列偏移,`*(...)` 解引用后得到元素值
// 方法 5:通过行指针 `array[i]` 偏移访问
cout << *(array[i] + j) << endl;
// 解释:`array[i]` 是指向第 i 行的行首指针
// `+ j` 是列偏移,`*(...)` 解引用后得到元素值
// 方法 6:通过行指针数组 `ptr3[i]` 偏移访问
cout << *(ptr3[i] + j) << endl;
// 解释:`ptr3[i]` 是指向第 i 行的行首指针
// `+ j` 是列偏移,`*(...)` 解引用后得到元素值
}
}
//输出5次1234
#pragma endregion
#pragma region 总结
//理解数组指针怎么用
//array和*array
//array => 数组指针变量 指向的是第一行一维数组的首地址(数组为单位去偏移)
// 类型 (*指针名)[列容量]
//*array => 对应类型的指针变量 指向的是第一行一维数组的第一个元素的首地址(元素为单位去偏移)
// 类型* 指针名
#pragma endregion
}
21.3 练习题
有一个二维数组array,请说明array、array[0]、&array[0][0]的作用和区别
- 假设二维数组类型是
int
array
- 作用:是获取到二维数组的首地址,二维数组中第一个一维数组的首地址。
- 偏移规则:使用它进行加减偏移时,是以元素所占字节数*列数来决定偏移多少的。
- 偏移单元:它的偏移最小单元是一个一维数组的容量。
- 偏移方向:因此它是按照行去偏移的。
- 本质:是一个数组指针
int (*)[列数]
。
array[0]
- 作用:是获取到二维数组中第一行的一维数组首地址。
- 偏移规则:使用它进行加减偏移时,是以元素所占字节数进行偏移的。
- 偏移单元:它的偏移最小单元是一个
int
(具体是什么类型由二维数组的类型决定)。 - 偏移方向:因此它是按照元素去偏移的。
- 本质:是一个
int
指针int*
。
&array[0][0]
- 作用:是获取二维数组中第一行第一列元素的地址。
- 偏移规则:使用它进行加减偏移时,是以元素所占字节数进行偏移的。
- 偏移单元:它的偏移最小单元是一个
int
(具体是什么类型由二维数组的类型决定)。 - 偏移方向:因此它是按照元素去偏移的。
- 本质:是一个
int
指针int*
。
有一个二维数组array,请说明一下表达式代表什么
&array[n][m]、array[n] + m、*(array + n) + m、代表什么?
以及
array[n][m]、*(array[n] + m)、*(*(array + n) + m) 又代表什么?
int array[2][3] = { 1, 2, 3, 4, 5, 6 };
// &array[n][m] => 第n行第m列元素的地址
// array[n] + m => 第n行一维数组地址,在该行的首地址基础上偏移m个元素单位 = 第n行第m列元素的地址
// *(array + n) + m => 先偏移n行地址,然后取出第n行一维数组的地址,在该行的首地址基础上偏移m个元素单位 = 第n行m列元素的地址
cout << &array[1][1] << endl; // 00000024504FF8A8
cout << array[1] + 1 << endl; // 00000024504FF8A8
cout << *(array + 1) + 1 << endl; // 00000024504FF8A8
// array[n][m] => 第n行第m列元素的值
// *(array[n] + m) => 第n行第m列元素的值
// *(*(array + n) + m) => 第n行第m列元素的值
cout << array[1][1] << endl; // 5
cout << *(array[1] + 1) << endl; // 5
cout << *(*(array + 1) + 1) << endl; // 5
声明一个 2x3 的二维数组 arr 并初始化为 123456。编写代码输出每个元素的值,使用指针访问二维数组中的每个元素。注意:禁止使用下标运算符 []
// int* p = &array[0][0];
// int (*ptr)[3] = array;
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
{
// 外层循环:用于遍历二维数组的行
// sizeof(array) / sizeof(array[0]) 计算二维数组的行数
// sizeof(array): 获取整个二维数组的总字节大小
// sizeof(array[0]): 获取二维数组中一行的字节大小
// 整个数组大小 / 每行大小 = 行数
for (int j = 0; j < sizeof(array[0]) / sizeof(int); j++)
{
// 内层循环:用于遍历当前行的列
// sizeof(array[0]) / sizeof(int): 计算当前行的列数
// sizeof(array[0]): 获取二维数组中第一行的字节大小
// sizeof(int): 一个元素的字节大小
// 第一行字节大小 / 单个元素大小 = 列数
cout << *(*(array + i) + j) << endl;
// **访问二维数组中的元素**
// *(array + i): 计算第 i 行的地址
// *(array + i) 相当于 array[i],是第 i 行的首地址
// *(array + i) + j: 在第 i 行的首地址基础上,偏移 j 个元素
// *(*(array + i) + j): 访问偏移后位置的值,相当于 array[i][j]
}
}
21.4 练习题代码
Lesson21_练习题.cpp
#include <iostream>
using namespace std;
int main()
{
std::cout << "指针和二维数组 练习题\n";
#pragma region 练习题一
/*有一个二维数组array
请说明array、array[0]、&array[0][0]的作用和区别*/
//假设 二维数组类型是 int
//array
//作用:是获取到二维数组的首地址,二维数组中第一个一维数组的首地址
// 使用它进行 加减 偏移时 是以 元素所占字节数*列数 来决定偏移多少的
// 它的偏移最小单元 是一个一维数组的容量
// 因此 它是按照行去偏移的
//本质:是一个数组指针 int (*)[列数]
//array[0]
//作用:是获取到二维数组中第一行的一维数组首地址
// 使用它进行 加减 偏移时 是以 元素所占字节数进行偏移的
// 它的偏移最小单元 是一个int(具体是什么类型 由二维数组的类型决定)
// 因此 它是按照元素去偏移的
//本质:是一个int指针 int*
//&array[0][0]
//作用:是获取二维数组中第一行第一列元素的地址
// 使用它进行 加减 偏移时 是以 元素所占字节数进行偏移的
// 它的偏移最小单元 是一个int(具体是什么类型 由二维数组的类型决定)
// 因此 它是按照元素去偏移的
//本质:是一个int指针 int*
#pragma endregion
#pragma region 练习题二
/*有一个二维数组array
请说明
&array[n][m]、
array[n] + m、
*(array + n) + m、
代表什么?
以及
array[n][m]、
*(array[n] + m)、
*(*(array + n) + m)
又代表什么*/
int array[2][3] = { 1,2,3,
4,5,6 };
// &array[n][m] => 第n行第m列元素的地址
// array[n] + m、=> 第n行一维数组地址, 在该行的首地址基础上偏移m个元素单位 = n行m列元素的地址
// *(array + n) + m、先偏移n行地址,然后取出第n行一维数组的地址,在该行的首地址基础上偏移m个元素单位
// = 第n行m列元素的地址
cout << &array[1][1] << endl;//00000024504FF8A8
cout << array[1] + 1 << endl;//00000024504FF8A8
cout << *(array + 1) + 1 << endl;//00000024504FF8A8
//array[n][m]、=> 第n行第m列元素的值
//*(array[n] + m)、=> 第n行第m列元素的值
//*(*(array + n) + m) => 第n行第m列元素的值
cout << array[1][1] << endl;//5
cout << *(array[1] + 1) << endl;//5
cout << *(*(array + 1) + 1) << endl;//5
#pragma endregion
#pragma region 练习题三
//声明一个 2x3 的二维数组 arr 并初始化为{ {1, 2, 3}, {4, 5, 6} }。
//编写代码输出每个元素的值,要求使用指针访问二维数组中的每个元素
//(禁止使用下标运算符[])
//int* p = &array[0][0];
//int (*ptr)[3] = array;
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
{
// 外层循环:用于遍历二维数组的行
// sizeof(array) / sizeof(array[0]) 计算二维数组的行数
// sizeof(array): 获取整个二维数组的总字节大小
// sizeof(array[0]): 获取二维数组中一行的字节大小
// 整个数组大小 / 每行大小 = 行数
for (int j = 0; j < sizeof(array[0]) / sizeof(int); j++)
{
// 内层循环:用于遍历当前行的列
// sizeof(array[0]) / sizeof(int): 计算当前行的列数
// sizeof(array[0]): 获取二维数组中第一行的字节大小
// sizeof(int): 一个元素的字节大小
// 第一行字节大小 / 单个元素大小 = 列数
cout << *(*(array + i) + j) << endl;
// **访问二维数组中的元素**
// *(array + i): 计算第 i 行的地址
// *(array + i) 相当于 array[i],是第 i 行的首地址
// *(array + i) + j: 在第 i 行的首地址基础上,偏移 j 个元素
// *(*(array + i) + j): 访问偏移后位置的值,相当于 array[i][j]
}
}
#pragma endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com