#279. 第二节 指针
第二节 指针
一、地址
对于程序中的变量,主要信息有以下三个:
- 信息存储在何处
- 存储的值是多少
- 存储的信息是什么类型
对于后两个我们已经比较熟悉,信息存储的地方我们称之为地址。对于某个变量,只需对变量应用地址运算符(&),就可以得到它的地址。如果num是一个变量,则&num即是num的地址。
#include<iostream>
using namespace std;
int main(){
int num = 3;
cout << "num的值为" << num << endl;
cout << "num的地址为 " << &num << endl;
}
预期输出:
num的值为3
num的地址为 0x6afe0c
请注意,实际的内存地址(如上例中的0x6afe0c)会根据程序的运行环境和编译器的不同而变化。上述输出中的地址仅为示例。
二、指针
指针是用于存储值的地址的变量。指针名表示的是地址。*运算符被称为间接值或解除引用运算符,将其应用于指针,可以得到该地址处存储的值。例如,如果point是一个指针,则point表示的是一个地址,而*point表示的是存储在该地址中的值。
#include<iostream>
using namespace std;
int main(){
int num = 3;
int* point; // 定义一个存放整型变量地址的指针
point = # // 将num变量的地址存入point。
cout << "num的值为" << *point << endl;
cout << "num的地址为 " << point << endl;
}
预期输出:
num的值为3
num的地址为 0x6afe04
请注意,实际的内存地址(如上例中的0x6afe04)会根据程序的运行环境和编译器的不同而变化。上述输出中的地址仅为示例。
1. 指针的声明
对于不同类型的变量,使用的字节数可能是不同的,它们存储值时使用的内部格式也不同。所以指针声明时需要指定指针指向的数据类型。例如:int* point就是声明了一个指向整型变量的指针。

对于如图所示的写法,则是定义了一个指针(point)与整型变量num。
2. 指针的初始化
指针初始化应为其赋值一个同类型的地址,如下图:

3. 指针与数组
数组的数组名即为数组的首地址,即对于:

指针变量p中存放的就是数组a的起始地址,所以a[i]等价于p[i]等价于*(p + i)等价于*(a + i)等价于a[i]。
4. 从二维指针到n维指针
指针同样也需要计算机为其分配内存来存储,所以我们可以定义“指向指针的指针”。例如:
#include<iostream>
using namespace std;
int main(){
int num = 3;
int* point = #
int** ptr = &point;
cout << "num的地址为" << point << endl; // point中存放的是变量num的地址
cout << "num的地址为" << *ptr << endl; // ptr中存放的是point的地址,
// *ptr即取point地址中的内容,即num的地址
cout << "num的值为" << **ptr << endl; // *ptr是num的地址,则**ptr为num的值。
return 0;
}
输出结果:
num的地址为0x7ffee4c0a4d4
num的地址为0x7ffee4c0a4d4
num的值为3
同理,可以再定义指向指针的指针的指针……,我们需要熟悉*与&的具体含义,即可弄清这里的逻辑。
三、练习题
- CSPJ2022第一轮 运行以下代码片段的行为是:

{{ select(1) }}
- 将x的值赋为201
- 将y的值赋为101
- 将q指向x的地址
- 将p指向y的地址
- 模拟题 以下代码片段的输出是:

{{ select(2) }}
- 3
- 4
- num的地址
- p的地址
- 模拟题 设p1和p2是指向同一个字符串的指针变量,c是字符变量,则以下说法错误的是:
{{ select(3) }}
- c = *p1 + *p2
- p2 = c
- p1 = p2
- c = *p1
- 模拟题 有以下语句:

设0 ≤i < 5,对a数组引用不正确的是:
{{ select(4) }}
- *( &a[i])
- a[p - a]
- *( * (a+i))
- p[i]