指针(Pointer)
一句话目标:理解”变量住在内存的哪个地址”,并用一种专门的类型 —— 指针 —— 去保存和使用这个地址。
第一部分:变量放在哪?—— 内存地址
程序运行时,每个变量都住在内存里的某个地址(门牌号)。用 & 取出变量的地址:
int n = 35;
cout << n; // 35 —— 值
cout << &n; // 0x7ffe... —— n 所在的地址
&叫取地址运算符。每个变量都有自己的地址。
第二部分:指针 —— 专门存地址的类型
指针是一种新的数据类型,专门用来存放其他数据的地址。
定义指针时要声明它指向什么类型的数据:
int n = 35;
int* p; // p 是"指向 int 的指针"
p = &n; // 让 p 存放 n 的地址(p 指向 n)
int* q = &n; // 定义时直接初始化读法:
int* p—— “p 是一个指针,指向 int”。指向的类型可以是基本类型、结构、类、数组、函数,甚至void。
第三部分:解引用 —— 通过指针访问变量
用 * 解引用,顺着地址找到那个变量的值:
int n = 35;
int* p = &n;
cout << *p; // 35 —— 顺着 p 找到 n 的值
*p = 100; // 通过 p 修改 n
cout << n; // 100 —— n 真的被改了!⚠️ 两个符号别搞混:
- 定义时的
int* p和解引用的*p都用*;&n是取地址,*p是取”指针指向的值”。它们互为逆操作。
第四部分:指针运算
指针能做加减,而且很聪明:p + 1 不是地址加 1 字节,而是跳到下一个元素(按指向类型的大小自动算)。
int a[5] = {10, 20, 30, 40, 50};
int* p = a; // 数组名就是首元素地址,p 指向 a[0]
cout << *p; // 10
cout << *(p + 1); // 20 —— 跳到下一个 int
p++; // p 现在指向 a[1]所以
a[i]等价于*(a + i)—— 这正是指针与数组的本质联系(呼应 06.数组(一维与二维))。
第五部分:sizeof 运算符
sizeof 算出某类型 / 变量占多少字节:
cout << sizeof(int); // 4
cout << sizeof(double); // 8
cout << sizeof(char); // 1
int a[10];
cout << sizeof(a); // 40 —— 10 个 int可用于基本类型、结构体、数组、类、指针。
第六部分:了解一下(不必深究)
- 指针数组:一个数组,每个元素都是指针。
- 二级指针:指向指针的指针(
int** pp),入门阶段知道有这回事即可。 - 指针与字符串:
char*可以指向字符串,C 风格字符串就靠它。
小结
- 每个变量有地址,
&取地址。 - 指针是存地址的类型:
int* p = &n;。 *p解引用取值,可读可改。- 指针
+1跳一个元素;a[i]==*(a+i),指针与数组同源。 sizeof算字节数。
课后小练
- 定义
int n,用指针p修改n的值并输出,体会”通过地址改值”。 - 用指针遍历数组
a[5]并求和(用*(p+i))。 - 输出
int、double、char、某数组的sizeof。