使用单次malloc分配的二维数组如何初始化和访问数组成员
单malloc分配二维数组的访问与内存结构说明
访问与初始化方法
你提到的array[0] + (char *)1写法是错误的:一方面int*类型指针和char*类型指针直接相加属于非法运算,另一方面int类型通常占4字节(依平台而定),仅偏移1字节只会取到单个int元素的部分字节,无法得到正确的array[0][1]的值。
正确的访问方式非常简单,直接使用二维数组下标即可,array[i][j]就代表第i行第j列的元素,也可以用等价的指针写法*(array[i] + j),两种写法效果完全一致。
初始化和访问的完整示例代码如下:
#include <stdio.h> #include <stdlib.h> #include <stddef.h> int main() { size_t i, j; unsigned int nrows = 2; unsigned int ncolumns = 3; int **array; const size_t row_pointers_bytes = nrows * sizeof *array; const size_t row_elements_bytes = ncolumns * sizeof **array; array = malloc(row_pointers_bytes + nrows * row_elements_bytes); if (array == NULL) { perror("内存分配失败"); return 1; } int * const data = array + nrows; for(i = 0; i < nrows; i++) { array[i] = data + i * ncolumns; } // 初始化数组元素 for (i = 0; i < nrows; i++) { for (j = 0; j < ncolumns; j++) { array[i][j] = i * 10 + j; } } // 遍历访问元素 for (i = 0; i < nrows; i++) { for (j = 0; j < ncolumns; j++) { printf("array[%zu][%zu] = %d\t地址:%p\n", i, j, array[i][j], &array[i][j]); } } free(array); return 0; }
如果你确实需要按字节偏移访问元素,正确写法为*(int*)((char*)array[0] + sizeof(int) * 1),但该写法可读性差易出错,日常开发不推荐使用。
内存结构图示
你通过单malloc申请的是一块连续的内存空间,整体分为两个区域:
- 行指针区:长度为
nrows * sizeof(int*),用来存储每行元素的首地址,也就是array[0]、array[1]的存储位置 - 数据存储区:紧跟在行指针区之后,长度为
nrows * ncolumns * sizeof(int),按行优先的顺序存储所有数组元素
以32位系统(指针和int都占4字节)、malloc返回的起始地址为0x1000为例,内存布局如下:
| 内存地址 | 存储内容 |
|---|---|
| 0x1000 | array[0]的值:0x1008(第一行元素首地址) |
| 0x1004 | array[1]的值:0x1014(第二行元素首地址) |
| 0x1008 | array[0][0] |
| 0x100C | array[0][1] |
| 0x1010 | array[0][2] |
| 0x1014 | array[1][0] |
| 0x1018 | array[1][1] |
| 0x101C | array[1][2] |
内容的提问来源于stack exchange,提问作者Milan
相关产品推荐
相关产品推荐

