我被指示使用单个matrix3D
命令将我的2d数组memcpy
中的所有元素复制到我的3d数组malloc2d
,然后打印出3d数组(用逗号,带分号的行和带有新行的每个2d矩阵。在此之前,程序接受用户输入三维矩阵的维度,然后所有数据进入矩阵(浮点数)。我的函数malloc3d
和memcpy
工作正常,我没有分段错误,但是当我尝试#include "utilities.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
unsigned int dim1,dim2,dim3;
printf("Dimensionality of 3-D matrix ===>");
scanf("%u",&dim1); //takes user input for dimensions
scanf("%u",&dim2); //takes user input for dimensions
scanf("%u",&dim3); //takes user input for dimensions
//allocating memory for 3d, 2d and 1d matrices
float*** matrix3D = malloc3D((unsigned int)(dim1), (unsigned int)(dim2), (unsigned int)(dim3), sizeof(float));
float** matrix2D = malloc2D(dim1, dim2*dim3, sizeof(float));
float* matrix1D = malloc(dim1*dim2*dim3);
for(int i = 0; i<(dim1*dim2*dim3); i++){ //taking user input floats
fscanf(stdin, "%f", &matrix1D[i]);
}//for
for(int i = 0; i<(dim1*dim2*dim3); i++){//writing contents of 1d matrix to 2d matrix
matrix2D[i/(dim2*dim3)][i%(dim2*dim3)] = matrix1D[i];
}//for
for (int i = 0; i < dim1; i++){//printing out 2d array as asked
for (int j = 0; j < (dim2*dim3); j++){
printf("%0.2f", matrix2D[i][j]);
if(j==((dim2*dim3)-1)){
printf(";");
}//if
else{
printf(",");
}//else
}//for
}//for
printf("\n"); //new line for readability
memcpy(matrix3D, matrix2D, dim1*dim2*dim3*sizeof(float));
for (int i = 0; i < dim1; i++){//printing out 3d array as asked
for (int j = 0; j < dim2; j++){
for(int k = 0; k < dim3; k++){
printf("%0.2f", matrix3D[i][j][k]);
if(j==((dim2)-1)){
printf(";");
}//if
else if(k==((dim3)-1)){
printf("\n");
}//else if
else{
printf(",");
}//else
}//for
}//for
}//for
free3D(matrix3D);
free2D(matrix2D);
free(matrix1D);
} //main
数据然后打印3d矩阵时,什么都没有打印。这是代码:
void** malloc2D(size_t rows, size_t cols, size_t sizeOfType){
void* block = malloc(sizeOfType * rows * cols);
void** matrix = malloc(sizeof(void*) * rows);
for (int row = 0; row < rows; ++row) {
matrix[row] = block + cols * row * sizeOfType;
}//for
return matrix;
}//malloc2D
void free2D(void*** matrix){
free((*matrix)[0]);
free((*matrix));
*matrix = NULL;
}//free2D
void*** malloc3D(size_t depth, size_t rows, size_t cols, size_t sizeOfType){
void* block = malloc(sizeOfType * rows * cols * depth);
void** matrix = malloc(sizeof(void*) * rows * depth);
void*** matrix2 = malloc(sizeof(void**) * depth);
for (int depth1 = 0; depth1 < depth; ++depth1) {
matrix2[depth1] = (void**)(matrix + depth * rows * sizeof(void**));
for(int row = 0; row < rows; ++row){
matrix[depth1 * rows + row] = block + (depth1 * rows + row) * cols * sizeOfType;
}//for
}//for
return matrix2;
}//malloc3D
void free3D(void**** matrix){
free((*matrix)[0][0]);
free((*matrix)[0]);
free((*matrix));
*matrix = NULL;
}//free3D
给出的示例输入和输出是(我除了最后2行之外还有所有打印 - 3d矩阵):
这是malloc2D,malloc3D,free2D和free3D。我的印象是他们是对的,因为在我们没有人能够得到它之后,它们就被送给了我们。
{{1}}
答案 0 :(得分:2)
使用单个memcpy
将2d数组复制到3d数组中的唯一方法是,每个2d和3d数组的数据在内存中都是平坦的。
您提供的分配函数显示每个函数的数据是连续的。因此,您需要将2d数组的数据部分复制到3d数组的数据部分。
由于数据是连续的,因此数据部分位于数组的第一个元素的地址处。因此,2d阵列的数据部分从&matrix2D[0][0]
开始,3d阵列的数据部分从&matrix3D[0][0][0]
开始。给定数组语法的语义,这些表达式分别与matrix2D[0]
和matrix3D[0][0]
相同。
假设matrix1D
已正确初始化:
memcpy(matrix2D[0], matrix1D, dim1*dim2*dim3*sizeof(float));
memcpy(matrix3D[0][0], matrix2D[0], dim1*dim2*dim3*sizeof(float));
答案 1 :(得分:0)
我已经看过几次这样的分配代码了,我总是指出这一点 虽然这是一种为双/三指针分配空间的聪明方法,但是 不小心使用时可能会遇到问题。
我们来看看Edittext
:
malloc2D
就像我之前指出的那样,{C}中的void*
pointer arithmetic is illegal,
GNU C有一个扩展。但我们假设这是按预期工作的:
第一个void** malloc2D(size_t rows, size_t cols, size_t sizeOfType){
void* block = malloc(sizeOfType * rows * cols);
void** matrix = malloc(sizeof(void*) * rows);
for (int row = 0; row < rows; ++row) {
matrix[row] = block + cols * row * sizeOfType;
}//for
return matrix;
}
为大小的对象保留malloc
个空格
rows * cols
。第二个sizeOfType
为malloc
指针保留空间。记忆
布局是(箭头表示:指针指向):
请注意rows
和block
以及不同的内存位置matrix
(matrix[i]
行)
指向i
处的序列的开始(新列的开头,多个
block[j]
)。
cols
基本上是相同但多次(malloc3D
次)。
基本的内存布局与另外一层相似
指针 1 :
请注意,depth
,block
和matrix
是不同的内存位置
matrix2
指向matrix2[i]
处的序列的开头
matrix[j]
指向matrix[j]
处序列的开头。
现在你做的时候:
block[k]
您不将memcpy(matrix3D, matrix2D, dim1*dim2*dim3*sizeof(float));
指向的内容复制到指向的内容中
到matrix2D
; matrix3D
的内容不是matrix2D
,而是float
三分球!所以你实际上是在matrix2D
中复制matrix3D
的指针。
这会引起麻烦,因为指针的类型不同(参见
图表):matrix2D
指针指向float*
和matrix3D
指针指向
float**
,所以当你取消引用它们时,你会得到错误的结果,因为你
从错误的地址解除引用。正如jxh在his/her answer中指出的那样,这会
只有当值在内存中是平的时才起作用,但它们不是,即使如此
block
是平的,但您无法直接访问block
,而您正在访问
通过指针。
这意味着
free3D(matrix3D);
free2D(matrix2D);
会让你遇到麻烦,因为第一个free
没有释放内存
由malloc3D
保留,因为它已被memcpy
覆盖。 free2D
会试图释放你不允许的同一记忆。
您必须转到block
级别并在那里使用memcpy
例如,这没关系:
for(int i = 0; i < rows; ++i)
memcpy(matrix3D[0][i], matrix2D[i], cols * sizeof(float));
<强> Fotenotes 强>
1 由于图表空间有限,我使用depth == 2
,所以
这就是matrix2+1
指向matrix+2
的原因。