使用双指针实现二维数组,为何各行内存未按预期连续?
为什么双指针实现的二维数组各行内存不连续?
我想用双指针实现二维数组,期望每个子数组在内存空间中连续,各行之间应间隔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**实现的:
- 第一次
malloc分配的是一个指针数组,里面每个元素都是指向int数组的指针; - 循环里的
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
相关产品推荐
相关产品推荐

