You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用双指针实现二维数组,为何各行内存未按预期连续?

为什么双指针实现的二维数组各行内存不连续?

我想用双指针实现二维数组,期望每个子数组在内存空间中连续,各行之间应间隔20字节(COL=5,int占4字节,5×4=20)。但运行以下代码后得到的结果与预期不符,能否解释为何各行内存不连续?

#define ROW 5
#define COL 5

int main() {
  int **ptr = (int **)malloc(sizeof(int *)*ROW);
  for(int i=0; i<ROW; i++) {
    *(ptr+i) = (int *)malloc(sizeof(int)*COL);
  }

  printf("%p\n", *(ptr+0));
  printf("%p\n", *(ptr+1));
  printf("%p\n", *(ptr+2));
  printf("%p\n", *(ptr+3));

return 0;
}

实际输出:

0000 0df3 4325 1450
0000 0df3 4325 1470
0000 0df3 4325 1490
0000 0df3 4325 14b0

预期输出:

0000 0df3 4325 1450
0000 0df3 4325 1464
0000 0df3 4325 1478
0000 0df3 4325 148c

问题根源

你当前的代码是**两次独立调用malloc**实现的:

  1. 第一次malloc分配的是一个指针数组,里面每个元素都是指向int数组的指针;
  2. 循环里的malloc是为每一行单独分配独立的内存块。

而malloc每次分配的内存块是彼此独立的,系统会从堆中寻找合适的空闲空间分配,这些空间没有强制连续的保证。另外,堆内存管理机制会给每个分配的内存块添加元数据(比如记录块大小、是否已分配),再加上系统的内存对齐要求(比如按16/32字节对齐),就会导致实际分配的地址间隔远大于你计算的20字节——你看到的32字节间隔(0x20)就是这个原因。

实现连续内存二维数组的正确方式

如果要让整个二维数组内存完全连续(行与行紧密排列),应该一次性分配足够的内存块,再通过指针数组映射各行地址:

#define ROW 5
#define COL 5

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 一次性分配可容纳ROW*COL个int的连续内存
    int *data = (int *)malloc(sizeof(int) * ROW * COL);
    // 分配指针数组,用于指向每一行的起始地址
    int **ptr = (int **)malloc(sizeof(int *) * ROW);
    
    for(int i=0; i<ROW; i++) {
        // 计算每一行的起始地址,保证行间隔为COL*sizeof(int)
        ptr[i] = data + i * COL;
    }

    // 打印各行地址
    for(int i=0; i<ROW; i++) {
        printf("%p\n", ptr[i]);
    }

    // 释放顺序:先释放指针数组,再释放数据块
    free(ptr);
    free(data);
    return 0;
}

这样输出的地址就会严格按照20字节间隔排列,因为所有行都在同一块连续内存中,行起始地址就是上一行起始地址加上COL*sizeof(int)。

另外还有更简单的方式:直接用一维数组模拟二维数组,通过data[i*COL + j]访问第i行第j列元素,不需要指针数组,内存同样完全连续。


内容的提问来源于stack exchange,提问作者Emre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:01:01