28.指针-指针数组
28.1 知识点
知识回顾:数组指针
数组指针是我们在学习指针和数组中,特别是二维数组相关知识时学习的重要概念。数组指针是一个指向整个数组的指针,其本质上是一个指针,指向一个包含 n 个元素的数组。
数组指针的定义规则
- 定义语法:
变量类型 (*指针名)[元素个数]
例如:int (*p2)[4]
表示一个指针,指向包含 4 个int
元素的一维数组。
示例代码
// 定义二维数组
int arr[3][4] = { 1,2,3,4,
5,6,7,8,
9,10,11,12 };
// 数组指针定义:指向包含4个整数的一维数组
int(*p)[4] = arr;
// 打印数组指针
// 打印数组指针 p 的地址和 p[0] 的地址
cout << "p: " << p << endl; // 打印p的地址,即指向的数组的起始地址
// 输出: p: 000000F33ACFF5E8
cout << "p[0]: " << p[0] << endl; // 打印p[0],即第一行数组的地址(arr[0]的地址)
// 输出: p[0]: 000000F33ACFF5E8
// 打印 p+1 和 p[1],它们指向的是第二行数组的地址
cout << "p+1: " << p + 1 << endl; // p+1:指向 arr[1](第二行数组)的地址
// 输出: p+1: 000000F33ACFF5F8
cout << "p[1]: " << p[1] << endl; // p[1]:指向 arr[1](第二行数组)的地址
// 输出: p[1]: 000000F33ACFF5F8
// 打印 p+2 和 p[2],它们指向的是第三行数组的地址
cout << "p+2: " << p + 2 << endl; // p+2:指向 arr[2](第三行数组)的地址
// 输出: p+2: 000000F33ACFF608
cout << "p[2]: " << p[2] << endl; // p[2]:指向 arr[2](第三行数组)的地址
// 输出: p[2]: 000000F33ACFF608
// 打印结解引用数组指针 (普通指针)
// 解引用数组指针 p
cout << "*p: " << *p << endl; // *p:解引用数组指针,访问arr[0](第一行数组)的地址
// 输出: *p: 000000F33ACFF5E8
// 解引用 p+1 和 p+2
cout << "*(p+1): " << *(p + 1) << endl; // 解引用p+1,访问arr[1](第二行数组)的地址
// 输出: *(p+1): 000000F33ACFF5F8
cout << "*(p+2): " << *(p + 2) << endl; // 解引用p+2,访问arr[2](第三行数组)的地址
// 输出: *(p+2): 000000F33ACFF608
//访问数组元素
// 解引用数组指针并访问元素
cout << "(*p)[1]: " << (*p)[1] << endl; // 解引用数组指针后,访问第一行数组中的第二个元素(arr[0][1]),输出 2
// 输出: (*p)[1]: 2
// 解引用并偏移后的结果
cout << "*((*p) + 1): " << *((*p) + 1) << endl; // 解引用数组指针并进行偏移,访问arr[0][1],即值为 2
// 输出: *((*p) + 1): 2
// 访问第二行第三列的元素
cout << "*(*(p + 1) + 2): " << *(*(p + 1) + 2) << endl; // 访问arr[1][2],输出 7
// 输出: *(*(p + 1) + 2): 7
// 访问第三行第四列的元素
cout << "*(*(p + 2) + 3): " << *(*(p + 2) + 3) << endl; // 访问arr[2][3],输出 12
// 输出: *(*(p + 2) + 3): 12
指针数组基本概念
指针数组是由多个指针组成的数组,每个指针可以存储一个地址,指向不同的元素。
定义规则
- 语法:
变量类型* 数组名[数组长度];
- 要点:
- 指针数组中的每个元素存储的是地址。
- 需要通过解引用操作(
*
)获取存储地址中的值。
示例代码
int* p2[4]; // 定义一个指针数组,包含4个指针元素
int a = 10; // 定义一个整数变量 a 并赋值为 10
p2[0] = &a; // 将 p2[0] 指向 a 的地址
// 打印指针数组中第一个元素(存储的是 a 的地址)
cout << "p2[0](地址): " << p2[0] << endl; // 输出:a 的地址
// 通过解引用 p2[0] 获取存储地址的值,即 a 的值
cout << "p2[0](值): " << *p2[0] << endl; // 输出:10(a 的值)
指针数组的使用
定义和操作
// 声明多个整型变量
int b = 11, c = 12;
// 定义一个指针数组,p3 存储了 a, b, c 的地址
int* p3[] = { &a, &b, &c };
// 打印指针数组中每个元素存储的地址
cout << "p3[0](地址): " << p3[0] << endl; // 输出:a 的地址
cout << "p3[1](地址): " << p3[1] << endl; // 输出:b 的地址
cout << "p3[2](地址): " << p3[2] << endl; // 输出:c 的地址
// 打印指针数组中每个元素存储的地址所指向的值
cout << "p3[0](值): " << *p3[0] << endl; // 输出:10
cout << "p3[1](值): " << *p3[1] << endl; // 输出:11
cout << "p3[2](值): " << *p3[2] << endl; // 输出:12
// 修改指向的地址
int d = 13;
p3[0] = &d; // 让 p3[0] 指向 d 的地址
// 打印新的地址和对应的值
cout << "p3[0](修改后地址): " << p3[0] << endl; // 输出:d 的地址
cout << "p3[0](修改后值): " << *p3[0] << endl; // 输出:13
// 修改指向的值
*p3[0] = 99; // 通过 p3[0] 修改 d 的值为 99
// 打印修改后的值
cout << "p3[0](修改后地址): " << p3[0] << endl; // 输出:d 的地址
cout << "p3[0](修改后值): " << *p3[0] << endl; // 输出:99
cout << "d(最终值): " << d << endl; // 输出:99
遍历指针数组
// 输出指针数组总大小和每个元素大小
cout << "得到指针数组一共占多少字节: " << sizeof(p3) << endl; // 输出:指针数组的总字节数 24
cout << "得到指针中一个元素占多少字节: " << sizeof(p3[0]) << endl; // 输出:每个指针元素的字节数 8
cout << "得到指针数组的容量: " << sizeof(p3) / sizeof(p3[0]) << endl; // 输出:指针数组的元素个数(容量)3
// 遍历指针数组并输出每个元素存储的地址和指向的值
for (int i = 0; i < sizeof(p3) / sizeof(p3[0]); i++) {
cout << "p3[" << i << "](地址): " << p3[i] << endl; // 输出每个元素的地址
cout << "p3[" << i << "](值): " << *p3[i] << endl; // 输出每个元素指向的值
}
地址关系
// 数组名 p3 代表指向指针数组首元素的地址
cout << "p3(指针数组名,表示首地址): " << p3 << endl;
cout << "&p3[0](数组名表示第一个元素的地址): " << &p3[0] << endl;
// 解引用指针数组中的第一个元素
cout << "*p3(指针数组第一个元素存储的地址): " << *p3 << endl;
// 解引用第二次,获得第一个元素存储的地址所指向的值
cout << "**p3(指针数组第一个元素指向的值): " << **p3 << endl;//99
// 指针数组的增减
// 获取指向第二个元素的指针
cout << "p3+1(指向第二个元素的地址): " << p3 + 1 << endl;
cout << "*(p3+1)(指向第二个元素的地址所指向的值): " << *(p3 + 1) << endl;
cout << "**(p3+1)(指向第二个元素的地址所指向的值): " << **(p3 + 1) << endl;//11
// 遍历并展示指针增减的效果
cout << "******遍历并展示指针增减的效果******" << endl;
for (int i = 0; i < sizeof(p3) / sizeof(p3[0]); i++) {
// 输出指针数组中第 i 个元素的地址
cout << "p3 + " << i << "(第 " << i << " 个元素的地址): " << p3 + i << endl;
// 输出指针数组中第 i 个元素存储的值(即地址)
cout << "*(p3 + " << i << ")(第 " << i << " 个元素的地址所指向的值): " << *(p3 + i) << endl;
// 输出指针数组中第 i 个元素中存储的地址指向的值
cout << "**(p3 + " << i << ")(第 " << i << " 个元素中存储的地址指向的值): " << **(p3 + i) << endl;
}
28.2 知识点代码
Lesson28_指针_指针数组.cpp
#include <iostream>
using namespace std;
int main()
{
std::cout << "指针数组\n";
#pragma region 知识回顾 数组指针
cout << "******知识回顾 数组指针******" << endl;
// 数组指针是我们在学习指针和数组中 二维数组相关知识时学习的
// 数组指针是一个指向整个数组的指针,本质上是一个指针,指向一个包含n个元素的数组
// 数组指针定义规则:变量类型 (*指针名)[元素个数]
// 例如 int (*p2)[4] 表示指向包含4个int元素的一维数组的指针
// 定义二维数组
int arr[3][4] = { 1,2,3,4,
5,6,7,8,
9,10,11,12 };
// 数组指针定义:指向包含4个整数的一维数组
int(*p)[4] = arr;
// 打印数组指针
// 打印数组指针 p 的地址和 p[0] 的地址
cout << "p: " << p << endl; // 打印p的地址,即指向的数组的起始地址
// 输出: p: 000000F33ACFF5E8
cout << "p[0]: " << p[0] << endl; // 打印p[0],即第一行数组的地址(arr[0]的地址)
// 输出: p[0]: 000000F33ACFF5E8
// 打印 p+1 和 p[1],它们指向的是第二行数组的地址
cout << "p+1: " << p + 1 << endl; // p+1:指向 arr[1](第二行数组)的地址
// 输出: p+1: 000000F33ACFF5F8
cout << "p[1]: " << p[1] << endl; // p[1]:指向 arr[1](第二行数组)的地址
// 输出: p[1]: 000000F33ACFF5F8
// 打印 p+2 和 p[2],它们指向的是第三行数组的地址
cout << "p+2: " << p + 2 << endl; // p+2:指向 arr[2](第三行数组)的地址
// 输出: p+2: 000000F33ACFF608
cout << "p[2]: " << p[2] << endl; // p[2]:指向 arr[2](第三行数组)的地址
// 输出: p[2]: 000000F33ACFF608
// 打印结解引用数组指针 (普通指针)
// 解引用数组指针 p
cout << "*p: " << *p << endl; // *p:解引用数组指针,访问arr[0](第一行数组)的地址
// 输出: *p: 000000F33ACFF5E8
// 解引用 p+1 和 p+2
cout << "*(p+1): " << *(p + 1) << endl; // 解引用p+1,访问arr[1](第二行数组)的地址
// 输出: *(p+1): 000000F33ACFF5F8
cout << "*(p+2): " << *(p + 2) << endl; // 解引用p+2,访问arr[2](第三行数组)的地址
// 输出: *(p+2): 000000F33ACFF608
//访问数组元素
// 解引用数组指针并访问元素
cout << "(*p)[1]: " << (*p)[1] << endl; // 解引用数组指针后,访问第一行数组中的第二个元素(arr[0][1]),输出 2
// 输出: (*p)[1]: 2
// 解引用并偏移后的结果
cout << "*((*p) + 1): " << *((*p) + 1) << endl; // 解引用数组指针并进行偏移,访问arr[0][1],即值为 2
// 输出: *((*p) + 1): 2
// 访问第二行第三列的元素
cout << "*(*(p + 1) + 2): " << *(*(p + 1) + 2) << endl; // 访问arr[1][2],输出 7
// 输出: *(*(p + 1) + 2): 7
// 访问第三行第四列的元素
cout << "*(*(p + 2) + 3): " << *(*(p + 2) + 3) << endl; // 访问arr[2][3],输出 12
// 输出: *(*(p + 2) + 3): 12
cout << "******知识回顾 数组指针结束******" << endl;
#pragma endregion
#pragma region 知识点一 指针数组基本概念
// 指针数组是由n个指针组成的数组,每个指针可以指向一个单独的元素地址
// 定义规则:变量类型* 数组名[数组长度];
// 重点:
// 指针数组中每个元素存储的是地址!!!!
// 想要获取地址中的值,需要加*(解引用操作)
// 举例:
int* p2[4]; // 定义一个指针数组,包含4个指针元素
int a = 10; // 定义一个整数变量 a 并赋值为 10
p2[0] = &a; // 将 p2[0] 指向 a 的地址
// 打印指针数组中第一个元素(存储的是 a 的地址)
cout << "p2[0](地址): " << p2[0] << endl; // 输出:a 的地址
// 通过解引用 p2[0] 获取存储地址的值,即 a 的值
cout << "p2[0](值): " << *p2[0] << endl; // 输出:10(a 的值)
#pragma endregion
#pragma region 知识点二 指针数组的使用
// 声明多个整型变量
int b = 11, c = 12;
// 定义一个指针数组,p3 存储了 a, b, c 的地址
int* p3[] = { &a, &b, &c };
// 打印指针数组中每个元素存储的地址
cout << "p3[0](地址): " << p3[0] << endl; // 输出:a 的地址
cout << "p3[1](地址): " << p3[1] << endl; // 输出:b 的地址
cout << "p3[2](地址): " << p3[2] << endl; // 输出:c 的地址
// 打印指针数组中每个元素存储的地址所指向的值
cout << "p3[0](值): " << *p3[0] << endl; // 输出:10
cout << "p3[1](值): " << *p3[1] << endl; // 输出:11
cout << "p3[2](值): " << *p3[2] << endl; // 输出:12
// 修改指向的地址
int d = 13;
p3[0] = &d; // 让 p3[0] 指向 d 的地址
// 打印新的地址和对应的值
cout << "p3[0](修改后地址): " << p3[0] << endl; // 输出:d 的地址
cout << "p3[0](修改后值): " << *p3[0] << endl; // 输出:13
// 修改指向的值
*p3[0] = 99; // 通过 p3[0] 修改 d 的值为 99
// 打印修改后的值
cout << "p3[0](修改后地址): " << p3[0] << endl; // 输出:d 的地址
cout << "p3[0](修改后值): " << *p3[0] << endl; // 输出:99
cout << "d(最终值): " << d << endl; // 输出:99
// 遍历指针数组
// 输出指针数组总大小和每个元素大小
cout << "得到指针数组一共占多少字节: " << sizeof(p3) << endl; // 输出:指针数组的总字节数 24
cout << "得到指针中一个元素占多少字节: " << sizeof(p3[0]) << endl; // 输出:每个指针元素的字节数 8
cout << "得到指针数组的容量: " << sizeof(p3) / sizeof(p3[0]) << endl; // 输出:指针数组的元素个数(容量)3
// 遍历指针数组并输出每个元素存储的地址和指向的值
for (int i = 0; i < sizeof(p3) / sizeof(p3[0]); i++) {
cout << "p3[" << i << "](地址): " << p3[i] << endl; // 输出每个元素的地址
cout << "p3[" << i << "](值): " << *p3[i] << endl; // 输出每个元素指向的值
}
// 地址关系
// 数组名 p3 代表指向指针数组首元素的地址
cout << "p3(指针数组名,表示首地址): " << p3 << endl;
cout << "&p3[0](数组名表示第一个元素的地址): " << &p3[0] << endl;
// 解引用指针数组中的第一个元素
cout << "*p3(指针数组第一个元素存储的地址): " << *p3 << endl;
// 解引用第二次,获得第一个元素存储的地址所指向的值
cout << "**p3(指针数组第一个元素指向的值): " << **p3 << endl;//99
// 指针数组的增减
// 获取指向第二个元素的指针
cout << "p3+1(指向第二个元素的地址): " << p3 + 1 << endl;
cout << "*(p3+1)(指向第二个元素的地址所指向的值): " << *(p3 + 1) << endl;
cout << "**(p3+1)(指向第二个元素的地址所指向的值): " << **(p3 + 1) << endl;//11
// 遍历并展示指针增减的效果
cout << "******遍历并展示指针增减的效果******" << endl;
for (int i = 0; i < sizeof(p3) / sizeof(p3[0]); i++) {
// 输出指针数组中第 i 个元素的地址
cout << "p3 + " << i << "(第 " << i << " 个元素的地址): " << p3 + i << endl;
// 输出指针数组中第 i 个元素存储的值(即地址)
cout << "*(p3 + " << i << ")(第 " << i << " 个元素的地址所指向的值): " << *(p3 + i) << endl;
// 输出指针数组中第 i 个元素中存储的地址指向的值
cout << "**(p3 + " << i << ")(第 " << i << " 个元素中存储的地址指向的值): " << **(p3 + i) << endl;
}
#pragma endregion
#pragma region 总结
// 对于指针数组来说,最重要的是理解指针数组在内存中存储信息的关系
// 主要理解值和地址的关系
// 指针数组名和本身地址的关系即可
#pragma endregion
}
28.3 练习题
编写一个程序,完成以下任务:
定义三个函数,分别实现以下功能:
add(int a, int b)
: 返回a
和b
的和。subtract(int a, int b)
: 返回a
和b
的差。multiply(int a, int b)
: 返回a
和b
的积。
创建一个指针数组,存储指向这些函数的指针。
通过指针数组调用每个函数,并打印结果。
// 返回 a 和 b 的和
int add(int a, int b)
{
return a + b;
}
// 返回 a 和 b 的差
int subtract(int a, int b)
{
return a - b;
}
// 返回 a 和 b 的积
int multiply(int a, int b)
{
return a * b;
}
// 创建一个函数指针数组,用于存储指向不同函数的指针
int (*functions[3])(int, int); // 数组大小为3,用于存储函数指针
// 为指针数组赋值,分别指向 add, subtract, multiply 函数
functions[0] = add;
functions[1] = subtract;
functions[2] = multiply;
// 遍历指针数组,调用每个函数并打印结果
for (int i = 0; i < sizeof(functions) / sizeof(functions[0]); i++)
{
int result = functions[i](10, 5); // 调用函数,传入 10 和 5 作为参数
cout << "函数结果: " << result << endl; // 打印函数返回值
}
// 函数结果: 15
// 函数结果: 5
// 函数结果: 50
编写一个程序,完成以下任务:
创建一个 3x3 的二维整型数组,并初始化如下:
1 2 3
4 5 6
7 8 9
创建一个指针数组,让每个指针指向二维数组的一行。
使用指针数组,输出二维数组中的所有元素。
// 定义一个 3x3 的二维数组,并初始化
int array[3][3] = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9} };
// 创建一个指针数组,每个元素指向二维数组的每一行
int* p[3] = { array[0], array[1], array[2] };
// 遍历指针数组,输出二维数组的所有元素
for (int i = 0; i < 3; i++) // 遍历每一行
{
for (int j = 0; j < 3; j++) // 遍历每一列
{
// 使用指针数组来访问二维数组中的元素
// p[i] 是指向第 i 行的指针,p[i][j] 访问第 i 行第 j 列的元素
cout << "元素[" << i << "][" << j << "]: " << p[i][j] << endl;
}
}
// 元素[0][0]: 1
// 元素[0][1]: 2
// 元素[0][2]: 3
// 元素[1][0]: 4
// 元素[1][1]: 5
// 元素[1][2]: 6
// 元素[2][0]: 7
// 元素[2][1]: 8
// 元素[2][2]: 9
28.4 练习题代码
Lesson28_练习题.cpp
#include <iostream>
using namespace std;
int add(int a, int b);
int subtract(int a, int b);
int multiply(int a, int b);
int main()
{
std::cout << "指针数组 练习题!\n";
#pragma region 练习题一
// 创建一个函数指针数组,用于存储指向不同函数的指针
int (*functions[3])(int, int); // 数组大小为3,用于存储函数指针
// 为指针数组赋值,分别指向 add, subtract, multiply 函数
functions[0] = add;
functions[1] = subtract;
functions[2] = multiply;
// 遍历指针数组,调用每个函数并打印结果
for (int i = 0; i < sizeof(functions) / sizeof(functions[0]); i++)
{
int result = functions[i](10, 5); // 调用函数,传入10和5作为参数
cout << "函数结果: " << result << endl; // 打印函数返回值
}
//函数结果: 15
//函数结果 : 5
//函数结果 : 50
#pragma endregion
#pragma region 练习题二
// 定义一个 3x3 的二维数组,并初始化
int array[3][3] = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9} };
// 创建一个指针数组,每个元素指向二维数组的每一行
int* p[3] = { array[0], array[1], array[2] };
// 遍历指针数组,输出二维数组的所有元素
for (int i = 0; i < 3; i++) // 遍历每一行
{
for (int j = 0; j < 3; j++) // 遍历每一列
{
// 使用指针数组来访问二维数组中的元素
// p[i] 是指向第 i 行的指针,p[i][j] 访问第 i 行第 j 列的元素
cout << "元素[" << i << "][" << j << "]: " << p[i][j] << endl;
}
}
//元素[0][0]: 1
//元素[0][1] : 2
//元素[0][2] : 3
//元素[1][0] : 4
//元素[1][1] : 5
//元素[1][2] : 6
//元素[2][0] : 7
//元素[2][1] : 8
//元素[2][2] : 9
#pragma endregion
}
#pragma region 练习题一
/*编写一个程序,完成以下任务:
1.定义三个函数,分别实现以下功能:
add(int a, int b):返回 a 和 b 的和。
subtract(int a, int b):返回 a 和 b 的差。
multiply(int a, int b):返回 a 和 b 的积。
2.创建一个指针数组,存储指向这些函数的指针。
3.通过指针数组调用每个函数,并打印结果。*/
// 返回 a 和 b 的和
int add(int a, int b)
{
return a + b;
}
// 返回 a 和 b 的差
int subtract(int a, int b)
{
return a - b;
}
// 返回 a 和 b 的积
int multiply(int a, int b)
{
return a * b;
}
#pragma endregion
#pragma region 练习题二
/*编写一个程序,完成以下任务:
1.创建一个 3x3 的二维整型数组,并初始化如下:
1 2 3
4 5 6
7 8 9
2.创建一个指针数组,让每个指针指向二维数组的一行。
3.使用指针数组,输出二维数组中的所有元素。*/
#pragma endregion
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com