基础知识点 | 0920_指针,数组指针,指针数组的总结及题目
入门知识点:
- 指针和指针变量是两个不同的概念,但要注意的是,通常我们叙述时会把指针变量简称为指针。
- 指针就是地址,地址就是指针,它是一个形无符号整型的一个整数。它的大小取决于系统是16,32 还是64位的 16/8=2byte,32/8=4byte,64/8=8byte.
- 指针变量其实是一个变量,只不过其存放的内容为地址,如
int* p
,这个p是指针类型,它的值存的是地址
基础知识点:
- 二维数组,数组指针,指针数组
//初始化二维数组a
int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
//指针
int *(p1[5]); //指针数组,可以去掉括号直接写作 int *p1[5];
int (*p2)[5]; //二维数组指针,不能去掉括号
- 内存中a的分布:
- 二维指针的指向方式如图:
-
指向二维数组的指针:
-
[]
的优先级高于*
,所以int (*p)[4]
和int *p[4]
不同。- 前者中,p是一个指针,指向一个数组,且数组的类型是int [4],
p+1
会使得指针移动16字节,指向a数组的下一行。 - 后者中,p是一个指针数组,内部存放4个指针,每个值是一个指针,指向一块地址。
- 前者中,p是一个指针,指向一个数组,且数组的类型是int [4],
/*
* Sep.20 2021 by july_iet
*
* 内存中数组a的存放方式是一维的:
* a[0] - a[1] - a[2] - a[3] - a[4] - a[5] - a[6] - a[7] - a[8] - a[9] - a[10] - a[11]
*
* 二维指针的指向方式:
* a(p) -> a[0](p) -> a[0][0] - a[0][1] - a[0][2] - a[0][3]
* -> a[1](p+1) -> a[1][0] - a[1][1] - a[1][2] - a[1][3]
* -> a[2](p+2) -> a[2][0] - a[2][1] - a[2][2] - a[2][3]
* -> a[3](p+3) -> a[3][0] - a[3][1] - a[3][2] - a[3][3]
*/
#include <iostream>
using namespace std;
int main() {
//初始化
int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
int(*p)[4] = a;
//part 1 :对 a 和 p 的操作是一样的
cout << "part 1 : " << endl;
cout << "整个数组的地址a : " << a << endl;
cout << "第0行的地址*a : " << *a << endl;
cout << "a[0][0] 的值 **a :" << **a << endl << endl;
cout << "整个数组的地址p : " << p << endl;
cout << "第0行的地址*p : " << *p << endl;
cout << "a[0][0] 的值 **p :" << **p << endl << endl;
//part 1 输出:
part 1 :
整个数组的地址a : 001AF8DC
第0行的地址*a : 001AF8DC
a[0][0] 的值 **a :0
整个数组的地址p : 001AF8DC
第0行的地址*p : 001AF8DC
a[0][0] 的值 **p :0
//part 2 : 取行地址的方式
cout << "part 2 : " << endl;
cout << "第1行的地址 a[1] : " << a[1] << endl;
cout << "第1行的地址 *(p+1) : " << *(p+1) << endl << endl;
//part 2 输出:
part 2 :
第1行的地址 a[1] : 001AF8EC
第1行的地址 *(p+1) : 001AF8EC
//part 3 : 奇妙尝试1 - 易混淆点
cout << "part 3 : " << endl;
cout << "a[1]第1行 的地址 *(a+1) : " << *(a+1) << endl;
cout << "a[0][1] 的地址 *a + 1 : " << *a + 1 << endl << endl;
//part 3 输出:
part 3 :
a[1]第1行 的地址 *(a+1) : 001AF8EC
a[0][1] 的地址 *a + 1 : 001AF8E0
//part 4 : 奇妙尝试2 - 一个实例
cout << "part 4 : " << endl;
cout << "a[1][1]+2 的值 *(*a+1) + 2 :" << *(*a+1) + 2 << endl;
cout << "a[1][2] 的值 (*(a+1))[2] :" << (*(a+1))[2] << endl;
//part 4 输出:
part 4 :
a[1][1]+2 的值 *(*a+1) + 2 :3
a[1][2] 的值 (*(a+1))[2] :6
return 0;
}
- 取值基础题:
-
p
--- 指向数组的开头a[0]
,指向第一行 -
*(p+1)
--- 相当于a[1]
,指向的内容是二维数组中对应第二行的数据 -
*(p+1)+1
--- 相当于&a[1][1]
,*(p+1)
放在表达式中表示第二行数据的首地址,可以直接做+j
操作,得到该行的第j位的地址 -
*(*(p+1)+1)
--- 相当于a[1][1]
,是该行的第j位的值
- 指针进阶题:
解答:
前者是指针数组,得到数组开头的值是"A4_Pi",后者是指向二维数组的指针,取数组开头的值仍是“A4_Pi”
解答:
B选项,b[i]
取第i行的地址,+j
后等同于&a[i][j]
,再利用*解引用;
C选项,*b
取第0行的地址b[0]
,+i
等同于b[0][i]
的地址,解引用后得到b[0][i]
的值,再对该值做+j
操作,相当于b[1][1]+2
;
D选项,*(b+i)
拿到第i行的地址b[i]
,通过[]
取b[i][j]
的值
解答:
需要注意的点在于strlen(x)
包含'/0'
,所以结果为5;
而语句*x = x[n]
将'/0'
赋值给了y[0]
;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)