如何在C语言中为已声明变量动态分配连续内存多维数组?
问题原因与解决方案
核心问题:类型不匹配
你代码里的foo->data是double**类型,而double (*array)[3]是指向包含3个double元素的一维数组的指针(也就是二维数组的行指针),这两种类型本质不同:
double**指向的是一个指针数组,每个元素又是指向double数组的指针;double (*)[3]指向的是一块连续的、按行排列的二维数组内存。
直接把array赋值给foo->data属于类型错误,编译器大概率会抛出警告。运行时访问foo->data[0][0]时,程序会把array指向的连续内存的前8字节(假设64位系统)当成一个指针去解引用,而这块内存实际是double数据,自然会导致崩溃。
解决方案一:修改结构体成员类型(推荐,符合连续内存需求)
把结构体里的double** data改成指向数组的指针类型,如果列数固定(比如你的例子里是3),可以直接写:
typedef struct { double (*data)[3]; // 指向包含3个double的数组的指针 /* other members */ } MyType;
对应的初始化代码无需强制类型转换,直接赋值即可:
MyType* init_function(/* args */) { MyType* foo = malloc(sizeof(MyType)); // 分配3行,每行3个double的连续内存 foo->data = malloc(3 * sizeof(*foo->data)); // 后续正常访问 foo->data[i][j] 即可 return foo; }
如果列数是动态的(运行时确定),C99及以后支持变长数组(VLA),可以这样定义结构体(注意这种结构体不能作为全局变量或静态变量,只能在函数内使用):
typedef struct { int cols; double (*data)[]; // 指向变长数组的指针 /* other members */ } MyType;
初始化代码调整为:
MyType* init_function(int rows, int cols) { MyType* foo = malloc(sizeof(MyType)); foo->cols = cols; // 分配rows行,每行cols个double的连续内存 foo->data = malloc(rows * sizeof(double[cols])); return foo; }
访问时可以用foo->data[i][j],和普通二维数组用法一致。
解决方案二:保留double**类型,但构造连续数据区
如果必须保留double**类型,需要先分配一个指针数组,再分配连续的二维数据内存,然后让每个指针指向连续内存的对应行起始位置:
MyType* init_function(int rows, int cols) { MyType* foo = malloc(sizeof(MyType)); // 1. 分配指针数组 foo->data = malloc(rows * sizeof(double*)); // 2. 分配连续的二维数据内存 double* continuous_data = malloc(rows * cols * sizeof(double)); // 3. 给每个行指针赋值 for (int i = 0; i < rows; i++) { foo->data[i] = continuous_data + i * cols; } return foo; }
这种方式下,数据是连续的,但指针数组本身是单独分配的内存。访问foo->data[i][j]可以正常工作,但释放内存时要注意顺序:先释放continuous_data,再释放foo->data,最后释放foo。
内容的提问来源于stack exchange,提问作者qbizzle68
相关产品推荐
相关产品推荐

