文章目录

C 语言指针:指针变量与地址操作

发布于 2026-04-18 09:24:14 · 浏览 9 次 · 评论 0 条

C 语言指针:指针变量与地址操作

C 语言指针的核心在于理解“内存地址”与“数据值”的关系。掌握指针变量和地址操作,能够直接对内存进行读写,是编写高效 C 程序的基础。


理解内存地址与变量

计算机内存被划分为一个个连续的存储单元,每个单元都有一个唯一的编号,这个编号就是内存地址。在程序中定义的变量,本质上就是向系统申请了一块内存区域来存储数据。

  1. 定义 一个整型变量并初始化。
    在代码中写入:

    int num = 10;

    此时,系统在内存中分配了空间(例如 4 个字节),并将 10 填入其中。假设这块内存的起始地址是 0x7ffee4

  2. 获取 变量的内存地址。
    使用取地址运算符 & 查看 num 的地址。

    printf("num 的地址: %p\n", &num);

    &num 表示“变量 num 的地址”。%p 是专门用于打印地址的格式控制符。


声明与初始化指针变量

指针变量是一种专门用来存储内存地址的变量。

  1. 声明 一个指针变量。
    指针声明时需要指定它指向的数据类型,这样系统才知道读取内存时要读取多少个字节。

    int *p;  // 声明一个指向整型的指针 p

    这里的 * 只是告诉编译器 p 是一个指针,此时 p 内部还没有存储有效的地址。

  2. 初始化 指针变量。
    将变量 num 的地址赋值 给指针 p

    p = #

    现在,p 的值就是 0x7ffee4(即 num 的地址)。我们称“p 指向了 num”。

  3. 验证 指针的值。
    运行 以下代码观察输出:

    printf("p 的值 (num 的地址): %p\n", p);
    printf("num 的地址: %p\n", &num);

    两者输出的结果完全一致。

为了更直观地理解这种指向关系,请参考下面的内存模型图:

graph LR subgraph Memory["内存空间"] direction TB PTR["指针变量 p\n地址: 0x2000\n值: 0x7ffee4"] NUM["变量 num\n地址: 0x7ffee4\n值: 10"] end PTR -- "存储内容指向" --> NUM

使用指针访问与修改数据

指针最强大的功能在于通过地址间接操作它指向的数据。

  1. 使用 解引用运算符 * 获取数据。
    在指针变量前使用 *,表示访问该地址处存储的数据。

    int value = *p;  // 读取 p 指向地址的值
    printf("*p 的值: %d\n", value); // 输出 10
  2. 通过 指针修改 原变量的值。
    执行 赋值操作:

    *p = 20;
    printf("num 的值: %d\n", num); // 输出 20

    虽然代码中只操作了 p,但因为 p 指向 num,所以 num 的值也变成了 20


指针的运算与数组

在 C 语言中,数组名本身就是一个地址(指向数组第一个元素的地址)。指针可以像数组下标一样遍历数据。

  1. 定义 数组并将指针指向数组首地址。

    int arr[3] = {100, 200, 300};
    int *ptr = arr; // 等同于 int *ptr = &arr[0];
  2. 通过 指针偏移访问 数组元素。
    对指针进行加法运算(如 ptr + 1)并不是简单的数值加 1,而是指向数组的下一个元素。地址的增加量取决于指针指向的数据类型(int 类型通常增加 4 个字节)。

    计算地址偏移的公式为:
    $$ \text{新地址} = \text{当前地址} + (\text{偏移量} \times \text{sizeof}(类型)) $$

    运行 以下代码查看效果:

    printf("第一个元素: %d\n", *ptr);       // 输出 100
    printf("第二个元素: %d\n", *(ptr + 1)); // 输出 200
    printf("第三个元素: %d\n", *(ptr + 2)); // 输出 300
  3. 使用 循环和指针遍历 数组。

    for (int i = 0; i < 3; i++) {
        printf("%d ", *(ptr + i));
    }

指针作为函数参数

C 语言中函数参数传递默认是“值传递”(复制一份副本)。如果要在函数内部修改函数外部变量的值,必须传递变量的地址(指针)。

  1. 编写 一个交换函数。
    如果直接传变量,无法交换外部实参的值。必须接收指针:

    void swap(int *x, int *y) {
        int temp = *x; // 取出地址 x 中的值
        *x = *y;       // 将 y 的值赋给 x 地址处的内存
        *y = temp;     // 将 temp 赋给 y 地址处的内存
    }
  2. 调用 函数时传递地址。

    int a = 5, b = 9;
    printf("交换前: a=%d, b=%d\n", a, b);
    
    swap(&a, &b); // 传递 a 和 b 的地址
    
    printf("交换后: a=%d, b=%d\n", a, b);

常见操作符速查表

符号 名称 作用 示例代码 含义
& 取地址符 获取变量在内存中的地址 int a = 10; int *p = &a; a 的地址赋给 p
* 解引用符 访问指针地址所存储的数据 int b = *p; 读取 p 指向的值赋给 b
* 声明符 声明一个指针变量 int *p; 定义一个名为 p 的整型指针

指针安全注意事项

在操作指针时,必须遵守以下规则以防止程序崩溃。

  1. 避免 野指针。
    指针在声明后若未初始化,其内部可能包含一个随机的垃圾地址。直接访问该地址会导致未定义行为或程序崩溃。
    修正 方法:声明时初始化NULL

    int *p = NULL; // 初始化为空
  2. 检查 指针是否为空。
    在使用指针前,务必判断它是否指向了有效内存。

    if (p != NULL) {
        *p = 10; // 安全操作
    }
  3. 防止 指针越界。
    当使用指针遍历数组时,确保指针移动范围不超过数组的边界。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文