#996. 指针入门
指针入门
指针
指针类型算是 C/C++ 中相对难理解的概念之一,是根本上区别于其它语种的内容之一,是可以直接操作内存的强大且风险较高的工具之一。
概念一定要清晰:指针是一种用于存储内存地址的数据类型。
需要明确一点,程序运行时的临时数据,都是存储在内存当中。而需要控制,操作该片内存之前,得先找到这片内存在哪,因此内存地址相当于是一片内存的标识。
int a;
a = 1;
cout << a << endl;
int a; 表示声明了一个整数类型的变量,名称为 a。这仅仅表示 a 这个变量名可以帮助程序操控一个 4 字节大小的内存。
a = 1; 表示将数字 1 存入 a 所表示的那片内存中。
因此 cout << a << endl; 可以输出 1 ,表示通过 a 变量查看那片内存中的数值。
int a;
int *p;
p = &a;
*p = 1;
cout << a << endl;
& 在这里被称为取地址符号,简称取址符,能够计算一个变量的内存地址。
int *p; 表示声明了一个 int 类型 的指针,名称为 p 。
在声明时,* 仅表示 p 是一个指针类型的变量。
注意这里明确了 p 是 int 类型 的指针,它只能用于存放 int 类型 变量的内存地址,不能够存储其它类型变量的内存地址。(除非使用强制类型转换)
在使用指针变量 p 时:
p变量存储的是内存地址*p表示这片内存,此刻*表示取值
例
int a = 1;
int *p = &a;
cout << &a << " " << a << endl; // a 的地址和 a 存的数值
cout << p << " " << *p << endl; // 输出数值 1 和与 &a 一样的地址
注意修改变量数值的本质,是修改内存中的数值。
指针基础运用
- 数组
- 函数
- sort
指针与数组
int a[10]; 表示声明了一个整数类型的数组,名称为 a,共 10 个元素,分别是 a[0], a[1], ... a[9]。
数组名称 a 有两层含义:表示这整个数组,也表明整个数组在内存中的首地址。
示例
int a[10];
cout << "首地址:" << &a[0] << endl;
cout << "数组名:" << a << endl;

可以观察到两个输出结果一致,表示名称 a 是一个int 类型的地址常量。
有如下用法:
int a[10] = {1, 3, 2, 4, 0, 9, 5, 6, 7, 8};
int *p = a; // 指针 p 存储数组 a 首地址,称之为 p 指向 a 的首地址
cout << "朴素数组运用" << endl;
for (int i = 0; i <= 9; i ++) {
cout << a[i] << " ";
}
cout << endl;
cout << "利用首地址偏移" << endl;
for (int i = 0; i <= 9; i ++) {
cout << *(a + i) << " ";
}
cout << endl;
cout << "利用指针变量偏移,这种遍历结束后,p 指针依然指向 a 数组的首地址" << endl;
for (int i = 0; i <= 9; i ++) {
cout << *(p + i) << " ";
}
cout << endl;
cout << "利用指针变量直接偏移,这种遍历结束后,p 指针不再指向数组 a" << endl;
for (int i = 0; i <= 9; i ++, p ++) {
cout << *p << " ";
}
cout << endl;
指针与函数
- 数值传递:
void foo(int x, int y);无法改变外界变量 - 引用传递:
void foo(int &x, int &y);可以改变外界变量,根本因素是传递了整片内存 - 地址传递 (指针传递):
void foo(int *px, int *py);直接传递内存地址,因为直接改变的是内存中的数据,因此只要是管理同片内存的存储单元都会被改变。
参考代码
void foo(int x, int y) {
int t;
t = x, x = y, y = t; // 外界变量不会交换
}
void foo(int &x, int &y) {
int t;
t = x, x = y, y = t; // 外界变量会被交换
}
void foo(int *px, int *py) {
int t;
t = *px, *px = *py, *py = t; // 外界变量会被交换
}
// 特别的,由于指针可以作为数组的首地址,因此函数传参数组可以有以下两种,且数组元素值若在函数内被改变,则外界数组必然被改变。
void foo(int a[], int n) {
// 当然 a 数组的下标范围要超过 n
for (int i = 1 ; i <= n; i ++) {
cout << a[i] << " ";
}
cout << endl;
}
void foo(int *a, int n) {
for (int i = 1; i <= n; i ++) {
cout << a[i] << " ";
}
cout << endl;
}
sort
对于sort 的参数,都是地址参数。具体参考 👉排序II
简单练习
-
以下对代码描述正确的是
int* p, q;
{{ select(1) }}
- p 和 q 都是指针
- p 和 q 都不是指针
- p 是指针,q 不是指针
- p 不是指针,q 是指针
- 以下代码是否正确
double b; int *p = &b;
{{ select(2) }}
- 不对
- 对
Related
In following homework: