我希望实现具有双指针的2D数组,并且我希望每个数组在内存空间中是连续的.因此每个数组之间应该有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;
}

100

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

100

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

推荐答案

您正在做的不是分配2D数组(即数组的数组).相反,您正在做的是分配一个1D指针数组,每个指针都指向一个int个元素的1Darray.这些数组可以位于内存中的任何位置,因为malloc返回的内存块不一定彼此相邻.

如果您想分配实际的2D数组,则应该使用对malloc的单一调用,以便确保所有内存是连续的.这是一个例子:

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

#define NUM_ROWS 5
#define NUM_COLS 5

int main( void )
{
    int (*ptr)[NUM_COLS] = malloc( sizeof *ptr * NUM_ROWS );
    if ( ptr == NULL )
    {
        fprintf( stderr, "memory allocation failure!\n" );
        exit( EXIT_FAILURE );
    }

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

    free( ptr );
}

此程序具有以下输出:

0x179c2a0
0x179c2b4
0x179c2c8
0x179c2dc

如您所见,子数组现在彼此相邻.所有地址之间的差异为20个字节.

在声明int (*ptr)[NUM_COLS]中,我已声明ptr是指向NUM_COLS个类型int个元素的数组的指针.我这样做是因为在C中,通常使用指向数组第一个元素的指针来引用数组,这样您就可以在指针上使用[]脚注操作符,以便访问数组的各个元素.

C++相关问答推荐

漏洞仅出现在FreeBSD上,但在Windows、Linux和MacOS上运行得非常好

C如何显示字符串数组中的第一个字母

在C中使用强制转换将uint16_t转换为uint8_t [2]是否有效?

从组播组地址了解收到的数据包长度

C:fopen是如何实现二进制模式和文本模式的?

当execvp在C函数中失败时杀死子进程

为什么内核使用扩展到前后相同的宏定义?

为什么net/if.h在ifaddrs.h之前?

LONG_DOUBLE_T是否存在(标准C:C23)

在C++中通过空指针隐式访问常量变量的值

CSAPP微型shell 实验室:卡在sigprocmask

Make Node函数.S有什么问题吗?

`#if`条件中是否允许`sizeof`?

C-使用指针返回修改后的整数数组

如何在CANbus RX/TX FIFO起始地址寄存器(ATSAME 51)的特定地址初始化数组?

为 struct 中的数组动态分配内存时出错

如何在不使用字符串的情况下在c中编写函数atof().h>;

将非连续物理内存映射到用户空间

区分MySQL C界面中的文本和BLOB字段

初始化动态分配的布尔二维数组的最佳方法是什么?