文章目录

C 语言指针操作:指针算术与数组访问的关系

发布于 2026-04-13 19:16:56 · 浏览 21 次 · 评论 0 条

C 语言指针操作:指针算术与数组访问的关系

C 语言中,数组名本质上是指向数组首元素的常量指针。理解指针算术与数组访问的等价性,是掌握 C 语言内存操作的核心。以下指南将通过内存原理解析与代码实操,详细拆解二者之间的转换关系。


1. 理解内存布局与指针步长

指针算术并不简单地改变地址的数值,而是根据数据类型的大小(sizeof(type))进行步进。

定义一个整型数组 int arr[4]。假设 int 类型占用 4 字节,数组首地址为 0x1000。内存分布如下:

  • arr[0] 地址:0x1000
  • arr[1] 地址:0x1004
  • arr[2] 地址:0x1008
  • arr[3] 地址:0x100C

计算指针移动的公式。当执行 ptr + 1 时,CPU 实际执行的地址偏移量计算如下:

$$Address_{new} = Address_{old} + (1 \times sizeof(int))$$

如果 ptr 指向 0x1000,则 ptr + 1 指向 0x1004,而非 0x1001。这保证了指针总是指向数组的下一个元素,而非下一个字节。


2. 对比数组下标与指针解引用

在 C 语言编译器内部,数组下标访问 arr[i] 会被自动转换为指针算术操作。这两种写法在底层生成的机器码是完全一致的。

访问方式 语法形式 指针算术等价形式 操作含义
数组下标 arr[i] *(arr + i) 取首地址偏移 i 个元素后的值
指针下标 ptr[i] *(ptr + i) 取指针当前地址偏移 i 个元素后的值
指针解引用 *(ptr + i) arr[i] 通过地址计算直接访问内存

3. 实操步骤:验证指针与数组的等价性

通过以下代码步骤,你可以直观地看到数组名如何作为指针使用,以及指针算术如何遍历数组。

步骤 1创建一个名为 pointer_array.c 的源文件,并输入以下代码:

#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int *ptr = arr; // 将数组首地址赋值给指针

    // 1. 使用数组下标访问
    printf("使用数组下标 arr[2]: %d\n", arr[2]);

    // 2. 使用指针算术访问
    // ptr + 2 计算地址,* 解引用取值
    printf("使用指针算术 *(ptr + 2): %d\n", *(ptr + 2));

    // 3. 验证指针的步长
    printf("ptr 地址: %p\n", (void*)ptr);
    printf("ptr + 1 地址: %p\n", (void*)(ptr + 1));

    // 4. 使用指针遍历数组
    printf("指针遍历数组: ");
    for (int i = 0; i < 5; i++) {
        // **注意**:这里混合使用了指针下标和算术
        printf("%d ", *(ptr + i)); 
    }
    printf("\n");

    return 0;
}

步骤 2编译运行该程序。在终端中执行命令:

gcc pointer_array.c -o pointer_array && ./pointer_array

步骤 3观察输出结果。你将看到 arr[2]*(ptr + 2) 输出了相同的值 30。同时,注意 ptrptr + 1 输出的十六进制地址差值为 4(在 64 位系统上 int 通常为 4 字节),证实了指针算术是基于数据类型的步长。


4. 进阶:指针与数组的细微差别

虽然数组名在表达式中常退化为指针,但二者并不完全等同。

区分以下两种操作场景:

  1. 取地址操作

    • 对数组名取地址 &arr 得到的是“整个数组的地址”,其类型是 int (*)[5](指向包含 5 个 int 的数组的指针)。
    • 对指针取地址 &ptr 得到的是指针变量自身在内存中的地址。
    • 验证&arr + 1 会跳过整个数组(20 字节),而 arr + 1 只跳过一个元素(4 字节)。
  2. 赋值操作

    • 数组名是常量指针,禁止修改。arr = ptr; 会导致编译错误。
    • 指针是变量,允许修改指向。ptr = arr;ptr++; 均为合法操作。

牢记:在函数参数传递中,数组参数总是退化为指向首元素的指针。因此,void func(int arr[])void func(int *arr) 是完全等价的声明。

评论 (0)

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

扫一扫,手机查看

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