1. 指针基础回顾与核心概念
在C语言中,指针是直接操作内存地址的变量。理解指针需要先掌握几个基本概念:
- 指针变量存储的是内存地址
- 通过解引用操作符(*)可以访问指针指向的值
- &运算符可以获取变量的内存地址
c复制int num = 42;
int *ptr = # // ptr指向num的地址
printf("%d", *ptr); // 输出42
指针的大小在不同系统架构下有所不同:
- 32位系统:4字节
- 64位系统:8字节
- 可通过sizeof(void*)查看
注意:指针类型必须与指向的数据类型匹配,否则可能导致未定义行为
2. 指针运算与数组关系
2.1 指针算术运算
指针支持四种基本运算:
- 指针与整数相加/减
- 指针递增/递减
- 指针相减
- 指针比较
c复制int arr[] = {10,20,30,40};
int *p = arr;
p++; // 移动到arr[1]
printf("%d", *(p+2)); // 输出40
2.2 数组名与指针
数组名在大多数情况下会退化为指向数组首元素的指针:
- arr == &arr[0]
- arr[i] 等价于 *(arr+i)
关键区别:
- sizeof(arr)返回整个数组大小
- sizeof(ptr)返回指针大小
3. 多级指针与复杂声明
3.1 二级指针
指向指针的指针常用于:
- 动态二维数组
- 修改指针参数的值
c复制int num = 42;
int *p = #
int **pp = &p;
printf("%d", **pp); // 输出42
3.2 复杂声明解析
使用"右左法则"解析复杂指针声明:
- 从标识符开始
- 先向右看,再向左看
- 遇到括号先解析括号内
示例:
c复制int *(*(*fp)(int))[10];
// fp是指向函数的指针,该函数接受int参数,返回指向10个int指针数组的指针
4. 函数指针与回调机制
4.1 基本用法
函数指针存储函数入口地址:
c复制int add(int a, int b) { return a+b; }
int (*funcPtr)(int,int) = add;
printf("%d", funcPtr(2,3)); // 输出5
4.2 典型应用场景
- 回调函数
- 策略模式实现
- 事件处理系统
c复制// 排序函数接受比较回调
void sort(int *arr, int n, int (*compare)(int,int)) {
// 使用compare进行元素比较
}
经验:typedef可以简化复杂函数指针声明:
c复制typedef int (*CompareFunc)(int,int);
5. 动态内存管理
5.1 基本操作
c复制int *p = malloc(10 * sizeof(int)); // 分配
if(p == NULL) { /* 处理错误 */ }
free(p); // 释放
p = NULL; // 避免悬垂指针
5.2 常见问题
- 内存泄漏
- 重复释放
- 访问已释放内存
- 内存越界
调试技巧:使用valgrind检测内存问题
6. 指针与结构体
6.1 结构体指针
c复制typedef struct {
int x;
char name[20];
} Point;
Point p1 = {5, "test"};
Point *ptr = &p1;
printf("%s", ptr->name); // 使用->访问成员
6.2 自引用结构
实现链表等数据结构:
c复制typedef struct Node {
int data;
struct Node *next;
} Node;
7. 指针安全与最佳实践
- 初始化指针为NULL
- 检查malloc返回值
- 释放后置NULL
- 注意指针作用域
- 避免返回局部变量指针
c复制// 安全示例
int *createArray(int size) {
int *arr = calloc(size, sizeof(int));
if(arr == NULL) {
fprintf(stderr, "分配失败");
exit(EXIT_FAILURE);
}
return arr;
}
8. 实战案例:指针实现字符串处理
c复制// 自定义字符串拷贝
char *my_strcpy(char *dest, const char *src) {
char *ret = dest;
while((*dest++ = *src++));
return ret;
}
// 计算字符串长度
size_t my_strlen(const char *s) {
const char *p = s;
while(*p) p++;
return p - s;
}
9. 指针与系统编程
9.1 内存映射
c复制int fd = open("file.txt", O_RDONLY);
char *mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
// 使用mapped访问文件内容
munmap(mapped, size);
9.2 多级指针在系统调用中的应用
c复制int pipefd[2];
pipe(pipefd); // pipefd[0]读端, pipefd[1]写端
10. 现代C语言指针特性
10.1 受限指针(C99)
c复制int *restrict ptr; // 表示ptr是访问数据的唯一方式
10.2 原子指针(C11)
c复制_Atomic int *atomicPtr;
掌握指针需要大量实践。建议从简单示例开始,逐步构建复杂应用,同时注意培养良好的内存管理习惯。调试工具如gdb和valgrind是理解指针行为的得力助手。
