什么是指针
C 语言里,每个变量都住在内存的某个位置,这个位置的编号就是内存地址。指针就是一种专门存放"地址"的变量。
打个比方:变量好比一个抽屉,里面放东西;指针好比一张写着"3 号抽屉"的纸条,它不装东西本身,而是告诉你东西放在哪里。
定义指针时,类型要和它指向的变量类型一致,写法是 类型 *名字:
int a = 10; // 普通变量
int *p = &a; // p 存的是 a 的地址
这里出现两个新符号,它们是一对镜像操作:
&a:取地址,读作"a 在哪",得到 a 的地址*p:解引用,读作"p 指着的那个变量",访问该地址上存的值
打印地址和通过指针读写
#include <stdio.h>
int main(void) {
int a = 10;
int *p = &a;
printf("%p\n", (void*)p); // 输出 a 的地址,形如 000000000061FE14(每次运行可能不同)
printf("%d\n", *p); // 输出:10(顺着地址取出值)
*p = 20; // 通过指针修改 a
printf("%d\n", a); // 输出:20
return 0;
}
可以看到,改 *p 就是改 a 本身——这正是指针的威力:可以从函数外部直接改动某个变量的值。
指针最经典的用途:swap 函数
初学者常见的困惑是"为什么函数里改了形参,外面的变量不变"。因为 C 的实参是值拷贝,函数拿到的是复印件。想让函数修改外部变量,就要把地址传进去:
#include <stdio.h>
void swap(int *x, int *y) {
int tmp = *x;
*x = *y;
*y = tmp;
}
int main(void) {
int a = 1, b = 2;
swap(&a, &b); // 传地址
printf("a=%d b=%d\n", a, b); // 输出:a=2 b=1,真的换过来了
return 0;
}
如果只传 int 不传指针,交换只发生在复印件上,函数返回后毫无变化。
指针与数组的关系
数组名在大多数场景下会退化成"指向首元素的指针",所以可以用指针遍历数组:
#include <stdio.h>
int main(void) {
int arr[4] = {10, 20, 30, 40};
int *p = arr; // 等价于 &arr[0]
printf("%d\n", *p); // 输出:10
printf("%d\n", *(p + 1)); // 输出:20,p+1 会跨过一个 int 的大小
for (int i = 0; i < 4; i++) {
printf("%d ", *(p + i)); // 输出:10 20 30 40
}
return 0;
}
*(p + i) 也可以写成 p[i],两者完全等价——数组下标本质上就是指针运算。
暂时"不指向任何地方":NULL
指针刚声明、还没确定指向谁时,先把它置为 NULL(空指针),解引用前先判断,这是必须养成的好习惯:
int *p = NULL;
if (p != NULL) {
printf("%d\n", *p); // 只有确认指向有效才解引用
}
小结
- 指针是存放内存地址的变量;
&取地址,*解引用,二者互逆 *p = 20会直接改变被指向变量的值- 想在函数里修改外部变量(比如 swap),必须传地址而不是传值
- 数组名会退化为首元素指针,
*(p + i)与p[i]等价 - 暂不使用的指针置
NULL,解引用前先判空
指针是 C 的灵魂,也是后续学习数组传参、字符串处理、动态内存的基础。先把它和"地址"的关系想清楚,后面就不会晕。
评论 0
还没有评论,来抢沙发吧~ 🛋