一、核心概念
指针是存储内存地址的变量,通过地址可以直接访问或修改对应内存中的数据。
- 内存地址:每个变量在内存中的唯一标识,类似于“房间号”。
- 指针变量:专门保存地址的变量,类型决定了解引用时访问的内存大小(如int*指针每次访问4字节)。
二、关键知识点
- 声明与初始化
int a = 10; // 普通整型变量 int *p = &a; // p是int类型指针,保存a的地址
- *表示指针类型,&取变量地址。
- 初始化必须:避免野指针(未初始化的指针)。
- 解引用操作
printf(“%d”, *p); // 输出p指向的值(即a的值) *p = 20; // 等价于 a = 20
- *在非声明语句中表示“访问指针指向的内存”。
- 指针与数组
int arr[3] = {1,2,3}; int *p = arr; // arr是数组首元素地址 printf(“%d”, p[1]); // 输出2(等价于*(p+1))
- 数组名是首元素地址,指针可通过加减法遍历数组。
- 指针作为函数参数
void change(int *p) { *p = 100; } int main() { int a=5; change(&a); } // a变为100
- 通过指针实现函数内外数据修改(传址调用)。
三、理解与记忆技巧
- 类比:指针像快递单号,内存地址是收货地址,*是拆箱操作。
- 口诀:&取地址,*解引用;类型匹配,初始化必行。
四、代码示例及逐行解析
#include <stdio.h> // 引入标准输入输出库 int main() { int a = 10; // 定义整型变量a,初始化为10 int *p = &a; // 定义指针p,指向a的地址(p存储的是a的地址) printf(“a的值:%d\n”, a); // 输出a的值,结果为10 printf(“通过指针访问的值:%d\n”, *p); // 解引用p,输出a的值,结果也是10 *p = 20; // 通过指针修改a的值为20(等价于a=20) printf(“修改后的a的值:%d\n”, a); // 再次输出a的值,结果为20 return 0; // 程序正常退出 }
五、代码解释
- #include 包含标准输入输出函数(如printf)所需的头文件。
- int a = 10;在栈内存中分配4字节空间存储整数10,变量名为a。
- int *p = &a;
- &a:获取变量a的地址(如0x7ffeeb1c)。
- int *p:声明一个int*类型的指针变量p。
- p = &a:将a的地址赋值给p,此时p指向a。
- printf(“a的值:%d\n”, a);直接输出变量a的值,结果为10。
- printf(“通过指针访问的值:%d\n”, *p);
- *p:解引用操作,访问p指向的内存(即a的值),输出10。
- *p = 20;
- 将20写入p指向的内存(即a的内存空间),此时a的值变为20。
- printf(“修改后的a的值:%d\n”, a);输出修改后的a的值,结果为20。
六、常见问题
- 空指针与野指针
- 空指针:int *p = NULL; 表示指针不指向任何有效内存。
- 野指针:未初始化的指针可能指向随机内存,导致程序崩溃。
- 指针类型的重要性
char c = ‘A’; int *p = (int*)&c; // 危险!类型不匹配,解引用可能越界访问
- 指针运算
int arr[3] = {10,20,30}; int *p = arr; p++; // p指向arr[1](地址增加sizeof(int)字节)
