C语言指针
大约 3 分钟
C 语言指针
配套Demo:codes/04_指针.c
指针是 C 语言的精髓:它存放的是变量的内存地址。
指针基础
int a = 10;
int *p = &a; // p 存放 a 的地址:& 取地址,* 定义指针/解引用
printf("%p\n", p); // a 的地址,如 0x7ffee3b4c8
printf("%d\n", *p); // 10,*p 解引用,访问地址上的值
*p = 20; // 通过指针修改 a
printf("%d\n", a); // 20
int **pp = &p; // 二级指针:指向指针的指针
printf("%d\n", **pp); // 20
野指针与 NULL
int *p1; // 未初始化的指针是野指针,禁止使用
int *p2 = NULL; // 指向空,使用前需判断
if (p2 != NULL) {
printf("%d\n", *p2);
}
指针与数组
数组名本质上是指向首元素的地址常量:
int arr[5] = {10, 20, 30, 40, 50};
int *p = arr; // 等价于 int *p = &arr[0];
printf("%d\n", *p); // 10
printf("%d\n", *(p + 1)); // 20,指针+1 移动一个元素的字节
printf("%d\n", p[2]); // 30,p[i] 等价于 *(p+i)
printf("%d\n", arr[3]); // 40
// 用指针遍历数组
for (int *q = arr; q < arr + 5; q++) {
printf("%d ", *q);
}
指针与字符串
char str[] = "hello"; // 字符数组,内容可修改
char *p = "world"; // 指向常量区的字符串,不可修改内容
while (*p) { // 遍历到 '\0' 结束
printf("%c", *p);
p++;
}
指针与函数
指针作参数:实现"引用传递"效果
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int main()
{
int a = 1, b = 2;
swap(&a, &b); // 传地址
printf("%d %d\n", a, b); // 2 1
return 0;
}
函数返回指针
不要返回函数内部局部变量的地址(函数调用结束栈帧销毁,地址失效);可以返回动态分配的内存或静态变量的地址。
函数指针
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int (*op)(int, int); // 定义函数指针变量
op = add;
printf("%d\n", op(3, 2)); // 5
op = sub;
printf("%d\n", op(3, 2)); // 1
// 函数指针数组:实现简单的运算分发
int (*ops[])(int, int) = {add, sub};
printf("%d %d\n", ops[0](10, 5), ops[1](10, 5)); // 15 5
函数指针是回调函数的基础,qsort 等标准库函数都依赖它。
动态内存管理(stdlib.h)
int *p = (int *)malloc(5 * sizeof(int)); // 申请内存,内容未初始化
if (p == NULL) { // 必须判空
return -1;
}
for (int i = 0; i < 5; i++) {
p[i] = i * 10;
}
int *q = (int *)calloc(5, sizeof(int)); // 申请并自动清零
p = (int *)realloc(p, 10 * sizeof(int)); // 扩容/缩容
free(p); // 用完必须释放,否则内存泄漏
free(q);
p = NULL; // 释放后置空,防止悬空指针
| 函数 | 说明 |
|---|---|
| malloc(size) | 分配 size 字节,不初始化 |
| calloc(n, size) | 分配 n×size 字节并清零 |
| realloc(ptr, size) | 调整已分配内存的大小 |
| free(ptr) | 释放内存 |
内存分区
- 栈区:局部变量、函数参数,由系统自动分配释放
- 堆区:malloc/calloc/realloc 手动分配,需手动释放
- 全局区/静态区:全局变量、static 变量
- 常量区:字符串常量等
- 代码区:程序指令
Loading...
