一篇介绍C语言中二级指针和二维数组的文章

我们知道C语言中指针也就是内存地址,指针变量是用来存放内存地址的变量。那么二级指针就是存放的指针的内存地址。int **arr 可以理解为一个二维数组的动态表示。它通常用于创建动态分配的二维数组,允许在运行时根据需要分配和管理内存。以下用一个例子和三个疑问来剖析二级指针和二维数组。

示例

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
int main() {
    int rows = 3, cols = 4;
    // Step 1: 分配行指针数组
    int **arr = (int **)malloc(rows * sizeof(int *));
    
    // Step 2: 为每一行分配内存
    for (int i = 0; i < rows; i++) {
        arr[i] = (int *)malloc(cols * sizeof(int));
    }
    // 填充数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            arr[i][j] = i * cols + j + 1; // 填充示例数据
        }
    }
    // 打印数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    // 释放内存
    for (int i = 0; i < rows; i++) {
        free(arr[i]); // 释放每一行的内存
    }
    free(arr); // 释放行指针数组
    return 0;
}

一、搞懂:真正的二维数组 vs 二级指针

真正的二维数组(栈上),它本质是:一维数组套一维数组

复制代码
int arr[3][4];

内存是一整块连续的

1\]\[2\]\[3\]\[4\]\[5\]\[6\]\[7\]\[8\]\[9\]\[10\]\[11\]\[12

用 malloc + int** 写的,内存不是连续的,结构是这样:

arr → 指针0 1234

指针1 \] → \[5\]\[6\]\[7\]\[8

指针2 \] → \[9\]\[10\]\[11\]\[12

  • arr 是一个指针,指向3 个指针
  • 这 3 个指针,每个又指向4 个 int
  • 所以可以用 arr[i][j]

二、为啥arrij == *(*(arr + i) + j)

在 C 语言中,数组下标运算 a[b] 被定义为 *(a + b)

在表达式中,数组名通常会退化为指向首元素的指针,因此 a[0] == *a 成立。

但需要注意:数组名本身不是指针,且该规则成立的前提是指针运算合法。

通过一步步运算我们可以得到arrij == *(*(arr+i)+j)

(arri)j --> *(arri +j) --> *(*(arr+i)+j)

含义:

  • arr+i → 找到第 i 行指针
  • *(arr+i) → 拿到第 i 行地址
  • *(arr+i)+j → 第 i 行第 j 列元素地址
  • *(*(arr+i)+j) → 取出元素

三、为啥free先free每行再free掉arr

现在的结构是:

arr → 存了3个指针

指针0 → 一行数据

指针1 → 一行数据

指针2 → 一行数据

所以释放顺序必须是:

  1. 先把3 行数据分别 free 掉
  2. 再 free 掉 arr 自己

如果先 free (arr),那三行数据的地址就丢了,变成内存泄漏

相关推荐
大草原的小灰灰15 分钟前
Python基础语法
开发语言·python
Logic10126 分钟前
C语言/数据动态规划题解:翻转一次子数组后的最大子数组和——四状态DP(O(n)时间O(1)空间)
c语言·数据结构·动态规划·时间复杂度·算法题·状态机dp·最大子数组和
泡泡鱼(敲代码中)2 小时前
MySQL基础学习笔记:从数据模型到DDL全掌握
开发语言·数据库·笔记·学习·mysql
Logic1012 小时前
C语言/数据结构字符串题解:找出DNA序列中未配对的独特序列——排序+遍历(O(nlogn))
c语言·数据结构·字符串·数组·排序·时间复杂度·算法题
Navigator_Z3 小时前
LeetCode //C - 1248. Count Number of Nice Subarrays
c语言·算法·leetcode
是隼人3 小时前
buuctf-pwn picoctf_2018_shellcode(ret2shellcode)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
潜创微科技3 小时前
IT6520:USB-C 转 MIPI 高集成控制器,DP 1.4a 转 MIPI 单芯片搞定 4K120 显示
c语言·开发语言·低延迟·掌机·联阳
Escalating_xu4 小时前
【System V 信号量】从 P/V 原语到 Builder 封装:写出可控、可清理的进程互斥组件
java·linux·开发语言·jvm
傲世仙尊4 小时前
System V 进程间通信详解:共享内存、消息队列与信号量(CSDN博客)
linux·开发语言·c++
cvby4 小时前
C++11
开发语言·c++