指针入门
嗨,我是长安!
说实话,指针是我当年学C语言时最难啃的骨头。我光是理解指针就花了一个多月,做了无数练习题。但现在回过头来看,其实并没有那么难。今天我来用最简单的方式,把指针给你讲明白。
指针是C语言的核心概念,也是最难理解的部分。但别怕,跟着我的节奏来,一定能学会!
什么是指针?
指针就是存储地址的变量。
类比理解
我当年就是用这个例子理解的,分享给你:
想象你住在一个小区:
- 房子 = 变量(存数据)
- 门牌号 = 地址
- 指针 = 记录门牌号的本子
graph LR
A[变量 age=18] -->|地址: 0x1000| B[内存地址]
C[指针 p] -->|存储| B
为什么需要指针?
工作这几年,我发现指针真的太重要了。它能让你:
- 直接操作内存 - 更高效
- 动态分配内存 - 灵活管理
- 函数修改参数 - 传递地址
- 数据结构 - 链表、树等
地址和取地址符 &
每个变量都有地址,使用 & 获取:
#include <stdio.h>
int main() {
int age = 18;
printf("age的值:%d\n", age);
printf("age的地址:%p\n", &age);
return 0;
}
输出:
age的值:18
age的地址:0x7ffeeb8a9a1c (每次运行可能不同)
指针的声明和使用
语法
数据类型 *指针名;
示例
#include <stdio.h>
int main() {
int age = 18;
int *p; // 声明指针
p = &age; // p指向age的地址
printf("age的值:%d\n", age);
printf("age的地址:%p\n", &age);
printf("指针p的值(地址):%p\n", p);
printf("指针p指向的值:%d\n", *p); // 解引用
return 0;
}
关键概念:
&age- 取age的地址*p- 通过指针访问值(解引用)
指针的三个重要操作
| 操作 | 符号 | 含义 | 示例 |
|---|---|---|---|
| 声明 | * | 声明指针变量 | int *p; |
| 取地址 | & | 获取变量地址 | p = &age; |
| 解引用 | * | 访问指针指向的值 | *p = 20; |
#include <stdio.h>
int main() {
int num = 10;
int *ptr = # // ptr指向num
printf("num = %d\n", num); // 10
printf("*ptr = %d\n", *ptr); // 10(通过指针访问)
*ptr = 20; // 通过指针修改值
printf("修改后 num = %d\n", num); // 20
return 0;
}
指针与函数
值传递 vs 指针传递
#include <stdio.h>
// 值传递(不能修改原变量)
void changeValue(int x) {
x = 100;
}
// 指针传递(可以修改原变量)
void changeByPointer(int *p) {
*p = 100;
}
int main() {
int a = 10, b = 10;
changeValue(a);
printf("值传递后 a = %d\n", a); // 10(没变)
changeByPointer(&b);
printf("指针传递后 b = %d\n", b); // 100(改变了)
return 0;
}
实例:交换两个数
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
printf("交换前:x=%d, y=%d\n", x, y);
swap(&x, &y);
printf("交换后:x=%d, y=%d\n", x, y);
return 0;
}
指针与数组
数组名就是指向第一个元素的指针!
#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *p = arr; // 等价于 p = &arr[0]
printf("arr[0] = %d\n", arr[0]); // 10
printf("*p = %d\n", *p); // 10
printf("*(p+1) = %d\n", *(p+1)); // 20
printf("p[2] = %d\n", p[2]); // 30
// 遍历数组
for (int i = 0; i < 5; i++) {
printf("%d ", *(p + i));
}
printf("\n");
return 0;
}
常见错误
错误1:未初始化指针
这个错误我当年犯过无数次:
int *p;
*p = 10; // ❌ 危险!p指向未知地址
正确做法:
int num;
int *p = #
*p = 10; // ✅ 安全
错误2:野指针
int *p = (int*)0x1234; // ❌ 随意指向一个地址
*p = 10; // 可能崩溃
错误3:悬空指针
int *p;
{
int num = 10;
p = #
}
// num已销毁,p变成悬空指针
*p = 20; // ❌ 危险
NULL指针
#include <stdio.h>
int main() {
int *p = NULL; // 空指针
if (p == NULL) {
printf("指针为空\n");
}
// 使用前检查
if (p != NULL) {
*p = 10;
}
return 0;
}
实战案例
案例1:数组求和(指针版)
#include <stdio.h>
int sumArray(int *arr, int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += *(arr + i);
}
return sum;
}
int main() {
int nums[] = {10, 20, 30, 40, 50};
int size = sizeof(nums) / sizeof(nums[0]);
int total = sumArray(nums, size);
printf("总和:%d\n", total);
return 0;
}
案例2:字符串长度
#include <stdio.h>
int stringLength(char *str) {
int len = 0;
while (*str != '\0') {
len++;
str++; // 指针移动
}
return len;
}
int main() {
char name[] = "Hello";
printf("长度:%d\n", stringLength(name));
return 0;
}
练习题
练习1:通过指针输入
用指针实现输入两个数并交换。
练习2:数组最大值
用指针找出数组最大值。
练习3:字符串复制
用指针实现字符串复制功能。
答案参考
查看答案
练习1:
#include <stdio.h>
void input(int *a, int *b) {
printf("输入两个数:");
scanf("%d %d", a, b);
}
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x, y;
input(&x, &y);
printf("原值:x=%d, y=%d\n", x, y);
swap(&x, &y);
printf("交换后:x=%d, y=%d\n", x, y);
return 0;
}
知识点总结
- ✅ 指针存储地址
- ✅
&取地址,*解引用 - ✅ 指针可以修改函数外的变量
- ✅ 数组名是指针
- ✅ 使用前初始化,用后检查NULL
下一步
👉 字符串详解
💡 学习建议
指针是难点,多写代码多实践!画图理解内存布局会很有帮助。