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)释放内存

内存分区

  1. 栈区:局部变量、函数参数,由系统自动分配释放
  2. 堆区:malloc/calloc/realloc 手动分配,需手动释放
  3. 全局区/静态区:全局变量、static 变量
  4. 常量区:字符串常量等
  5. 代码区:程序指令
Loading...