当前位置: 首页 > article >正文

C语言------二维数组指针从入门到精通

前言:

        目标:需要了解及掌握数组指针的行地址、列地址、具体元素地址、具体元素地址的值是怎样定义及实现。

        重点:指针的偏移,指针解引用。

        难点:指针的升阶与降阶。

1. 基本概念

  • 二维数组:二维数组可以看作是一个数组的数组。例如,int a[3][4] 表示一个 3 行 4 列的二维数组。

  • 数组指针:数组指针是一个指针,指向一个数组。例如,int (*p)[4] 表示一个指向包含 4 个整数的数组的指针。

  • 指针数组:指针数组是一个数组,其元素是指针。例如,int *p[3] 表示一个包含 3 个整型指针的数组。

  • 数组名与指针的区别

    • 数组名:在大多数情况下,数组名可以被视为指向其第一个元素的指针。

    • 指针:指针是一个变量,可以指向任何类型的变量,并且可以被重新赋值。

  • 指针运算

    • 指针加减:指针加减操作会根据指针类型调整偏移量。例如,int *p; p + 1 表示 p 向前移动一个 int 的大小。

    • 指针解引用:使用 * 运算符访问指针指向的值。

  • 二维数组的指针表示

    • int arr[3][4]; 中,arr 是一个指向 int [4] 的指针。

    • arr[0] 是一个指向 int 的指针,表示第一行的第一个元素。

    • arr[i] 等价于 *(arr + i),表示第 i 行的第一个元素。

  • 行地址和列地址的区别:二维数组中每一行的行地址和每一行第一列地址在数值上是相同的,但含义不同。行地址是指向整个行的指针,而列地址是指向行中某个元素的指针。

  • 二维数组的地址:二维数组的名字 a 本身就是一个指向第一行的指针,即 a 等价于 &a[0]

2.二维数组的内存布局

        对于二维数组 int arr[2][3];的内存布局如下:

        对于二维数组 int arr[3][4];,内存布局如下:

arr[0][0] arr[0][1] arr[0][2] arr[0][3]

arr[1][0] arr[1][1] arr[1][2] arr[1][3]

arr[2][0] arr[2][1] arr[2][2] arr[2][3]

        假设每个 int 占用4字节,内存地址如下:

arr[0][0] -> 0x7ffee3b8e990
arr[0][1] -> 0x7ffee3b8e994
arr[0][2] -> 0x7ffee3b8e998
arr[0][3] -> 0x7ffee3b8e99c
arr[1][0] -> 0x7ffee3b8e9a0
arr[1][1] -> 0x7ffee3b8e9a4
arr[1][2] -> 0x7ffee3b8e9a8
arr[1][3] -> 0x7ffee3b8e9ac
arr[2][0] -> 0x7ffee3b8e9b0
arr[2][1] -> 0x7ffee3b8e9b4
arr[2][2] -> 0x7ffee3b8e9b8
arr[2][3] -> 0x7ffee3b8e9bc

  3. 二维数组指针代码分析

#include <stdio.h> 
 
int main() { 
    int arr[3][4] = { 
        {1, 2, 3, 4}, 
        {5, 6, 7, 8}, 
        {9, 10, 11, 12} 
    }; 
 
    // 行地址 
    printf("第一行地址: %p\n", (void *)arr); 
    printf("第二行地址: %p\n", (void *)(arr + 1)); 
    printf("第三行地址: %p\n", (void *)(arr + 2)); 
 
    // 列地址 
    printf("第一行第一列地址: %p\n", (void *)arr[0]); 
    printf("第一行第二列地址: %p\n", (void *)(arr[0] + 1)); 
    printf("第二行第一列地址: %p\n", (void *)(*(arr + 1))); 
 
    // 具体元素地址 
    printf("a[1][2]的地址: %p\n", (void *)(arr[1] + 2)); 
    printf("a[1][2]的地址: %p\n", (void *)(*(arr + 1) + 2)); 
    printf("a[1][2]的地址: %p\n", (void *)&arr[1][2]); 
 
    // 具体元素的值 
    printf("a[1][2]的值: %d\n", *(arr[1] + 2)); 
    printf("a[1][2]的值: %d\n", *(*(arr + 1) + 2)); 
    printf("a[1][2]的值: %d\n", arr[1][2]); 
 
    return 0; 
}

4. 地址运算

  • & 运算符:地址升阶,将一个元素的地址提升为指向该元素所在行的指针。
  • *运算符:地址降阶,将一个行地址降阶为该行中某个元素的地址。

5.二维数组指针行地址表示

  • arr

    • arr 是一个指向 int [4] 的指针,表示第一行的地址。

    • 输出:0x7ffee3b8e990

  • arr + 1

    • arr + 1 是一个指向 int [4] 的指针,表示第二行的地址。

    • 输出:0x7ffee3b8e9a0

  • arr + 2

    • arr + 2 是一个指向 int [4] 的指针,表示第三行的地址。

    • 输出:0x7ffee3b8e9b0

6.二维数组指针列地址表示

  • arr[0]

    • arr[0] 是一个指向 int 的指针,表示第一行第一个元素的地址。

    • 输出:0x7ffee3b8e990

  • arr[0] + 1

    • arr[0] + 1 是一个指向 int 的指针,表示第一行第二个元素的地址。

    • 输出:0x7ffee3b8e994

  • *(arr + 1)

    • *(arr + 1) 等价于 arr[1],是一个指向 int 的指针,表示第二行第一个元素的地址。

    • 输出:0x7ffee3b8e9a0

7.二维数组指针具体元素地址表示

  • arr[1] + 2

    • arr[1] + 2 是一个指向 int 的指针,表示第二行第三个元素的地址。

    • 输出:0x7ffee3b8e9a8

  • *(arr + 1) + 2

    • *(arr + 1) + 2 等价于 arr[1] + 2,是一个指向 int 的指针,表示第二行第三个元素的地址。

    • 输出:0x7ffee3b8e9a8

  • &arr[1][2]

    • &arr[1][2] 是一个指向 int 的指针,表示第二行第三个元素的地址。

    • 输出:0x7ffee3b8e9a8

8.二维数组指针具体元素的值表示

  • *(arr[1] + 2)

    • *(arr[1] + 2) 解引用 arr[1] + 2,得到第二行第三个元素的值 7

    • 输出:7

  • *(*(arr + 1) + 2)

    • *(*(arr + 1) + 2) 解引用 *(arr + 1) + 2,得到第二行第三个元素的值 7

    • 输出:7

  • arr[1][2]

    • arr[1][2] 直接访问第二行第三个元素的值 7

    • 输出:7

9. 二维数组指针地址的输出

 // 行地址 
    printf("第一行地址: %p\n", (void *)arr); 
    printf("第二行地址: %p\n", (void *)(arr + 1)); 
    printf("第三行地址: %p\n", (void *)(arr + 2)); 
 
    // 列地址 
    printf("第一行第一列地址: %p\n", (void *)arr[0]); 
    printf("第一行第二列地址: %p\n", (void *)(arr[0] + 1)); 
    printf("第二行第一列地址: %p\n", (void *)(*(arr + 1))); 
 
    // 具体元素地址 
    printf("a[1][2]的地址: %p\n", (void *)(arr[1] + 2)); 
    printf("a[1][2]的地址: %p\n", (void *)(*(arr + 1) + 2)); 
    printf("a[1][2]的地址: %p\n", (void *)&arr[1][2]); 
 
    // 具体元素的值 
    printf("a[1][2]的值: %d\n", *(arr[1] + 2)); 
    printf("a[1][2]的值: %d\n", *(*(arr + 1) + 2)); 
    printf("a[1][2]的值: %d\n", arr[1][2]); 

9. 二维数组指针应用

        使用二维数组指针迎接财神。


http://www.kler.cn/a/530577.html

相关文章:

  • 首发!ZStack 智塔支持 DeepSeek V3/R1/ Janus Pro,多种国产 CPU/GPU 可私有化部署
  • sysbench压力测试工具mysql以及postgresql
  • 【xdoj-离散线上练习】T251(C++)
  • 基于UKF-IMM无迹卡尔曼滤波与交互式多模型的轨迹跟踪算法matlab仿真,对比EKF-IMM和UKF
  • 小程序项目-购物-首页与准备
  • Observability:实现 OpenTelemetry 原生可观察性的商业价值
  • 一文了解阿里的 Qwen2.5 模型
  • 79-《袋鼠花》
  • Java知识速记:栈和堆
  • Java synchronized的实现原理?
  • 问题的价值 ( Value of Question ) 公式
  • Games202Lecture5 Real time Environment mapping实时环境光照
  • ADC及DMA的使用原理和使用过程
  • 详细介绍:使用 Axios 上传图片文件
  • ESP32 Wroom (无串口芯片的简版C3) 烧录
  • 攻防世界 fileclude
  • 基于springboot+vue的哈利波特书影音互动科普网站
  • AMD架构简单读书笔记1
  • WSL2中安装的ubuntu搭建tftp服务器uboot通过tftp下载
  • 位运算算法题
  • 【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.13 零拷贝技巧:as_strided的魔法与风险
  • 【Linux系统】信号:信号保存 / 信号处理、内核态 / 用户态、操作系统运行原理(中断)
  • 进程控制-下篇
  • cpp的STL与java的Collections Framework使用
  • 汇编知识点汇总
  • MVC、MVP和MVVM模式