使用C中的memcpy将2D矩阵复制到3D矩阵

时间:2018-02-20 20:36:30

标签: c arrays matrix memcpy

我被指示使用单个matrix3D命令将我的2d数组memcpy中的所有元素复制到我的3d数组malloc2d,然后打印出3d数组(用逗号,带分号的行和带有新行的每个2d矩阵。在此之前,程序接受用户输入三维矩阵的维度,然后所有数据进入矩阵(浮点数)。我的函数malloc3dmemcpy工作正常,我没有分段错误,但是当我尝试#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矩阵):

example input/output

这是malloc2D,malloc3D,free2D和free3D。我的印象是他们是对的,因为在我们没有人能够得到它之后,它们就被送给了我们。

{{1}}

2 个答案:

答案 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。第二个sizeOfTypemalloc指针保留空间。记忆 布局是(箭头表示:指针指向):

请注意rowsblock以及不同的内存位置matrixmatrix[i]行) 指向i处的序列的开始(新列的开头,多个 block[j])。

cols基本上是相同但多次(malloc3D次)。 基本的内存布局与另外一层相似 指针 1

请注意,depthblockmatrix是不同的内存位置 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的原因。