如何复制“双指针”?

时间:2018-04-10 12:33:41

标签: c loops pointers copy

我是C的新手。我有一个具有这种结构的函数(这段代码不可重现,这是“伪代码”,但我希望它足以解释我的问题):

unsigned** myfunction(double*** A, unsigned nx, unsigned ny, unsigned nz){
    unsigned* cells[nz-1];
    unsigned totallength = 0;
    unsigned lengths[nz-1];
    unsigned** bottomTypes = function1(A, nx, ny, 0);
    for(unsigned k=0; k<nz-1; k++){
        unsigned** topTypes = function1(A, nx, ny, k+1);
        unsigned** cellTypes = function2(bottomTypes, topTypes);
        unsigned length
        unsigned** goodcells = function3(cellTypes, &length);
        cells[k] = malloc(length * sizeof(unsigned));
        for(unsigned l=0; l<length; l++){
            cells[k][l] = goodcells[0][l] + k;
        }
        lengths[k] = length;
        totallength += length;
        bottomTypes = function1(A, nx, ny, k+1); // the same as topTypes
    }
    unsigned** out = malloc(4 * sizeof(unsigned*));
    ......
    ......
    return out;
}

如您所见,在循环结束时,我执行bottomTypes = function1(A, nx, ny, k+1);,这与之前介绍的topTypes相同。因此function1(A,nx,ny,k+1)被调用两次。那是因为我无法在topTypes中复制bottomTypes。当我这样做时,代码产生了预期的输出。

不是这样做,为了避免doube电话,我已经尝试了

**bottomTypes = **topTypes;

bottomTypes = malloc((nx-1) * sizeof(unsigned*));
for ( int i = 0; i < nx-1; ++i ){
    bottomTypes[i] = malloc((ny-1)*sizeof(unsigned));
    memcpy(bottomTypes[i], topTypes[i], ny-1);
}

代码编译但是当我这样做时,我没有得到预期的结果。

topTypes复制到bottomTypes的正确方法是什么?

我希望这很清楚。否则不要犹豫,说我不清楚,我会尝试做一个再生的例子,但这并不容易。我在SO上发现了类似的问题,但没有一个能让我解决我的问题。

修改

下面是一个完整的再生示例。我承认,这并不是很小。

#include <stdlib.h> // for malloc
#include <stdio.h>  // for printf

// function to create a "three-dimensional array" (I know this is not the correct wording)
//  from a given function
double*** fun2array(double f(unsigned,unsigned,unsigned), unsigned nx, unsigned ny, unsigned nz){
    double*** out = (double***) malloc(nx * sizeof(double**));
    for(unsigned i=0; i<nx; i++){
        out[i] = (double**) malloc(ny * sizeof(double*));
        for(unsigned j=0; j<ny; j++){
            out[i][j] = (double*) malloc(nz * sizeof(double));
            for(unsigned k=0; k<nz; k++){
                out[i][j][k] = f(i,j,k);
            }
        }
    }
    return out;
}

// a three-dimensional array
double fun(unsigned i, unsigned j, unsigned k){
    return i+j+k;
}
double*** A = fun2array(fun, 2, 3, 4);

// function to "slice" a 3d-array to a 2D-array (a "matrix")
double** toMatrix(double*** A, unsigned nx, unsigned ny, unsigned k){
    double** out = (double**) malloc(nx * sizeof(double*));
    for(unsigned i=0; i<nx; i++){
        out[i] = (double*) malloc(ny * sizeof(double));
        for(unsigned j=0; j<ny; j++){
            out[i][j] = A[i][j][k];
        }
    }
    return out;    
}

// function to convert double matrix to integer matrix
unsigned** floorMatrix(double** M , unsigned nx, unsigned ny){
    unsigned** out = (unsigned**) malloc(nx * sizeof(unsigned*));
    for(unsigned i=0; i<nx; i++){
        out[i] = (unsigned*) malloc(ny * sizeof(unsigned));
        for(unsigned j=0; j<ny; j++){
            out[i][j] = (unsigned) M[i][j];
        }
    }
    return out;
}

// function to sum 2 "matrices"
unsigned** matricialSum(unsigned** M1, unsigned** M2, unsigned nx, unsigned ny){
    unsigned** out = (unsigned**) malloc(nx * sizeof(unsigned*));
    for(unsigned i=0; i<nx; i++){
        out[i] = (unsigned*) malloc(ny * sizeof(unsigned));
        for(unsigned j=0; j<ny; j++){
            out[i][j] = M1[i][j] + M2[i][j];
        }
    }
    return out;
}

unsigned myfunction(double*** A, unsigned nx, unsigned ny, unsigned nz){
    unsigned** bottomTypes = floorMatrix(toMatrix(A, nx, ny, 0), nx, ny);
    unsigned** cellTypes;
    for(unsigned k=0; k<nz-1; k++){
        unsigned** topTypes = floorMatrix(toMatrix(A, nx, ny, k+1), nx, ny);
        cellTypes = matricialSum(bottomTypes, topTypes, nx, ny);
        bottomTypes = floorMatrix(toMatrix(A, nx, ny, k+1), nx, ny); // the same as topTypes
    }
    return cellTypes[0][0];
}


int main(){
    unsigned result = myfunction(A, 2, 3, 4);
    printf("result:%u\n", result);
    return 0;
}

第二次编辑

我有一个解决方案,但确定不是最佳的:

unsigned** copyMatrix(unsigned** M, unsigned nx, unsigned ny){
    unsigned** MM = malloc(nx * sizeof(unsigned*));
    for(unsigned i=0; i<nx; i++){
        MM[i] = malloc(ny * sizeof(unsigned));
        for(unsigned j=0; j<ny; j++){
            MM[i][j] = M[i][j];
        }
    }
    return MM;
}

然后在示例代码中我释放bottomTypes然后我

unsigned** bottomTypes = copyMatrix(topTypes, nx-1, ny-1);

1 个答案:

答案 0 :(得分:1)

我终于理解了你的问题,你用**bottomTypes = **topTypes;代替bottomTypes = topTypes;。这只是用另一个替换指针。

但是你的代码有很多潜在的问题,你有内存泄漏,使用ThreeStar,你使用malloc返回等等。如果你使用C的目的是快,我建议你改变你的数据结构。 malloc()代价很高,除非您希望能够用O(1)交换矩阵的两行,否则不需要为你的矩阵的每一行都有一个malloc。

所以:

  • Do I cast the result of malloc?
  • 如果您不想要malloc()
  • ,可以使用FAM
  • 每次放弃topTypesbottomTypescellTypes时,您都会发生内存泄漏,我想这只是在你的[mcve]中。
  • 在您使用VLA的原始代码中,应谨慎使用。
  • 您使用无符号而不是size_t作为索引,如果您不使用非常大的矩阵,则不是一个大问题。

你的[mcve]几乎没有修复,内存泄漏无处不在:

#include <stdlib.h> // for malloc
#include <stdio.h>  // for printf

// function to create a "three-dimensional array" (I know this is not the
// correct wording)
//  from a given function
double ***fun2array(double (*f)(size_t, size_t, size_t), size_t nx, size_t ny,
                    size_t nz) {
  double ***out = malloc(nx * sizeof *out);
  for (size_t i = 0; i < nx; i++) {
    out[i] = malloc(ny * sizeof *out[i]);
    for (size_t j = 0; j < ny; j++) {
      out[i][j] = malloc(nz * sizeof *out[i][j]);
      for (size_t k = 0; k < nz; k++) {
        out[i][j][k] = f(i, j, k);
      }
    }
  }
  return out;
}

// a three-dimensional array
double fun(size_t i, size_t j, size_t k) { return i + j + k; }

// function to "slice" a 3d-array to a 2D-array (a "matrix")
double **toMatrix(double ***A, size_t nx, size_t ny, size_t k) {
  double **out = malloc(nx * sizeof *out);
  for (size_t i = 0; i < nx; i++) {
    out[i] = malloc(ny * sizeof *out[i]);
    for (size_t j = 0; j < ny; j++) {
      out[i][j] = A[i][j][k];
    }
  }
  return out;
}

// function to convert double matrix to integer matrix
unsigned **floorMatrix(double **M, size_t nx, size_t ny) {
  unsigned **out = malloc(nx * sizeof *out);
  for (size_t i = 0; i < nx; i++) {
    out[i] = malloc(ny * sizeof *out[i]);
    for (size_t j = 0; j < ny; j++) {
      out[i][j] = M[i][j];
    }
  }
  return out;
}

// function to sum 2 "matrices"
unsigned **matricialSum(unsigned **M1, unsigned **M2, size_t nx, size_t ny) {
  unsigned **out = malloc(nx * sizeof *out);
  for (size_t i = 0; i < nx; i++) {
    out[i] = malloc(ny * sizeof *out[i]);
    for (size_t j = 0; j < ny; j++) {
      out[i][j] = M1[i][j] + M2[i][j];
    }
  }
  return out;
}

unsigned myfunction(double ***A, size_t nx, size_t ny, size_t nz) {
  unsigned **bottomTypes = floorMatrix(toMatrix(A, nx, ny, 0), nx, ny);
  unsigned **cellTypes = bottomTypes;
  for (size_t k = 1; k < nz; k++) {
    unsigned **topTypes = floorMatrix(toMatrix(A, nx, ny, k), nx, ny);
    cellTypes = matricialSum(bottomTypes, topTypes, nx, ny);
    bottomTypes = topTypes;
  }
  return cellTypes[0][0];
}

int main(void) {
  double ***A = fun2array(fun, 2, 3, 4);
  unsigned result = myfunction(A, 2, 3, 4);
  printf("result:%u\n", result);
}