很多刚学 C 语言的小伙伴,一听到 “指针” 就头疼 ——“听说指针特别难,是不是要背好多公式?”“地址和指针到底啥关系?” 其实指针一点都不神秘,今天咱们用 “找朋友家” 的生活例子,把指针讲得明明白白,再配上简单代码,保证你看完就能上手。
目录
一、指针到底是个啥?
二、为什么需要指针
三、指针的基础操作:3 步学会用指针
1. 第一步:定义指针 —— 告诉编译器 “这是个指针”
2. 第二步:给指针赋值 —— 让指针 “指向具体变量”
3. 第三步:用指针访问数据 —— 通过地址找变量
四、实战:用指针解决 “交换变量” 问题
五、常见误区:别踩这 3 个坑
1:指针没赋值就用(野指针):
2:把变量值给指针:
3:混淆*的含义
一、指针到底是个啥?
咱们先想个日常场景: 假设你要去朋友小明家做客,有两种方式能找到他家:
1:直接去:你记得小明家具体地址(比如 “XX 小区 3 号楼 2 单元 501”),按地址直接找到;
2:问别人:你先问小红,小红说 “小明家地址在我笔记本第 10 页写着”,你先找到小红的笔记本第 10 页,拿到地址后再去小明家。
在 C 语言里,“变量” 就像 “小明家”,变量里存的数据就是 “小明本人”, “指针”,就是小明家的地址,“二级指针”就是小红的笔记本第 10 页,上面写着小明家的地址
二、为什么需要指针
可能有人会问:“我直接用变量名调用数据不就行了,为啥要绕一圈用指针?”
举个例子:如果要写一个 “交换两个变量值” 的函数,直接传变量名根本没用! 看这段错误代码:
#include
// 错误示例:直接传变量,无法交换
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int x = 10, y = 20;
swap(x, y); // 传的是x和y的“副本”,不是本身
printf("x=%d, y=%d\n", x, y); // 输出还是x=10, y=20,没交换!
return 0;
}
原因是:函数参数传的是 “变量副本”(形参),改副本不会影响原变量。但如果用指针,传的是 “变量的地址”,函数就能通过地址直接找到原变量,修改它的值 —— 这就是指针的核心用处:直接操作内存中的数据。
三、指针的基础操作:3 步学会用指针
要用上指针,就 3 个关键步骤:定义指针→给指针赋值(绑定地址)→用指针访问数据。
1. 第一步:定义指针 —— 告诉编译器 “这是个指针”
定义指针的格式很简单:数据类型 *指针名;
比如:
int *p; //定义一个 “指向 int 类型变量” 的指针,名叫 p
char *q //定义一个 “指向 char 类型变量” 的指针,名叫 q
这里的 " * " 是 “ 指针标志 ”,告诉编译器 “ p 不是普通变量,是存地址的指针 ”。
注意:*要跟指针名贴紧,比如int* p也能运行,但推荐int *p,更清晰。
2. 第二步:给指针赋值 —— 让指针 “指向具体变量”
指针不能随便用!必须先让它指向一个已存在的变量(就像先让小红的笔记本写上小明家地址,才能用)。
给指针赋值用&(取地址符),&变量名表示 “获取这个变量的内存地址”。
示例代码:
#include
int main()
{
int num = 100; // 先定义一个普通int变量num,值是100
int *p; // 定义指针p,指向int类型
p = # // 给p赋值:把num的地址存到p里(p现在指向num)
// 验证一下:输出num的地址和p的值(应该一样)
printf("num的地址:%p\n", &num); // %p是打印地址的格式符
printf("p的值(存的地址):%p\n", p);
return 0;
}
运行结果大概是这样(地址是 16 进制数,每个人电脑可能不一样):
num的地址:0x7ffee4b7658c8
p的值(存的地址):0x7ffee4b7658c8
这说明 p 确实存了 num 的地址,现在 p 和 num 就绑定了。
3. 第三步:用指针访问数据 —— 通过地址找变量
有了绑定好的指针,怎么用它读 /写变量的值?
用 *指针名(这里的*是 “解引用符”,表示 “通过指针存的地址,找到对应的变量”)。
还是刚才的例子,加一段访问代码:
#include
int main()
{
int num = 100;
int *p = # // 可以合并写:定义指针时直接赋值(推荐)
// 1. 用指针读数据:*p等价于num
printf("通过num读:%d\n", num); // 输出100
printf("通过p读:%d\n", *p); // 输出100(*p就是num的值)
// 2. 用指针改数据:改*p就是改num
*p = 200; // 通过p的地址,把num的值改成200
printf("改后num:%d\n", num); // 输出200(num真的变了!)
return 0;
}
这里的关键是:*p就等于num —— 读*p就是读num,改*p就是改num。
四、实战:用指针解决 “交换变量” 问题
现在咱们用指针改写开头的 “交换函数”,看看效果:
#include
// 正确示例:用指针传地址
void swap(int *a, int *b) // 参数是两个int类型指针
{
int temp = *a; // 用*a取指针a指向的变量值(即x)
*a = *b; // 把*b的值(y)赋给*a(x)
*b = temp; // 把temp的值(原x)赋给*b(y)
}
int main()
{
int x = 10, y = 20;
swap(&x, &y); // 传x和y的地址,让指针a、b指向它们
printf("x=%d, y=%d\n", x, y); // 输出x=20, y=10,成功交换!
return 0;
}
这次终于成功了!因为函数里的*a和*b直接操作的是x和y本身,不是副本。
五、常见误区:别踩这 3 个坑
1:指针没赋值就用(野指针):
int *p;
*p = 10; //p 没指向任何变量,乱改内存会导致程序崩溃,一定要先让指针指向已存在的变量。
2:把变量值给指针:
int num=10;
int *p;
p=num; //p 要存的是地址,不是 10 这个值,应该写p=&num。
3:混淆*的含义
定义时int *p的*是 “指针标志”,用的时候*p=20的*是 “解引用符”,别搞混