带指针的多维数组元素赋值

时间:2015-02-16 23:58:44

标签: c arrays pointers multidimensional-array

我有一个参差不齐的二维结构数组和一个分配并返回mystruct*的函数:

mystruct** arr;
mystruct* foo();

arr元素赋值的语法是什么?以下不起作用,但我想要类似的东西:

&arr[i][j]=foo();

这是一个简化的例子:

typedef struct mystruct{
    int a,b,c,d;
} mystruct;

mystruct* foo()
{
    mystruct* x = (mystruct*)malloc(sizeof(mystruct));
    x->a=1;
    x->b=1;
    x->c=1;
    x->d=1;
    return x;
}

int main()
{
    int rows=3;
    int cols=4;

    mystruct** arr;
    arr = (mystruct**) malloc(sizeof(mystruct*)*rows);
    for(int i=0;i<rows;i++)
    {
        arr[i]=(mystruct*)malloc(sizeof(mystruct)*cols);
    }

    for (int i=0;i<rows;i++)
    {
        *(arr[i][0]) = foo();
    }

    return 0;
}

我已经删除了我的大部分主程序,但上面的代码仍然给了我error: no match for ‘operator*’ (operand type is ‘mystruct’)

在实际代码中mystruct很大,数组的尺寸很大。

3 个答案:

答案 0 :(得分:1)

如果你真的希望mystruct的所有实例都在一个分配中(即保持foo不变)那么数组可以是:

int main()
{
    int rows=3;
    int cols=4;

    mystruct *(*arr)[cols] = malloc( rows * sizeof *arr );

    for(int i=0; i<rows; i++)
        arr[i][0] = foo();

    // note: arr[i][1] etc. are uninitialized 

    free(arr);
}

当每行的长度相同时,不需要为数组的每一行使用单独的malloc,而是可以对一个块进行malloc。并don't cast malloc


如果您不需要每行一次分配,并且您很乐意构造mystruct void bar(mystruct *p),并使用指向某个已分配存储的指针调用mystruct,那么您的数组可以存储{{1直接对象:

mystruct (*arr)[cols] = malloc( rows * sizeof *arr );

for ( int i = 0; i < rows; ++i )
    bar( &arr[i][0] );

答案 1 :(得分:0)

*(arr[i][j]) = foo();会将指向2d数组中struct的指针值设置为指向foo返回的struct,如果这是你真正想要的那样。

如果您只想保留2d到struct的指针数组,那么您可以将数组声明更改为mystruct* arr[3][4]并使用arr[i][j] = foo()

答案 2 :(得分:-1)

我认为使用一些抽象将有助于这种情况。我急忙写了下面的例子,但我希望它有所帮助。

更新:根据评论更改。仍然在gcc下编译,现在干净地穿过Valgrind。

#include <stdio.h>
#include <stdlib.h>

typedef struct SomeStruct SomeStruct;
struct SomeStruct {
  int foo;
  int bar;
};
typedef SomeStruct* SomeStruct_ptr;
typedef struct SomeStructMat SomeStructMat;
typedef SomeStructMat* SomeStructMat_ptr;
struct SomeStructMat {
  int rows;
  int cols;
  SomeStruct_ptr** data;
};

SomeStruct_ptr somestruct_new(int foo, int bar) {
  SomeStruct_ptr ssp = malloc(sizeof(SomeStruct));
  ssp->foo = foo;
  ssp->bar = bar;
  return ssp;
}

void somestruct_destroy(SomeStruct_ptr ssp) {
  free(ssp);
}

SomeStruct_ptr** somestructmat_new(int rows, int cols) {
  int r, c;
  SomeStruct_ptr** mat = malloc( rows * sizeof(SomeStruct_ptr*) );

  for(r = 0; r < rows; ++r) {
    mat[r] = malloc(sizeof(SomeStruct_ptr) * cols);
    for(c = 0; c < cols; ++c) {
      mat[r][c] = somestruct_new(0,0);
    }
  }
  return mat;
}

SomeStructMat_ptr SomeStructMat_new(int rows, int cols) {
  SomeStructMat_ptr mat = malloc(sizeof(SomeStructMat));
  mat->rows = rows;
  mat->cols = cols;
  mat->data = somestructmat_new(rows, cols); 
  return mat;
}

void SomeStructMat_destroy(SomeStructMat_ptr mat) {
  int r,c;
  for(r = 0; r < mat->rows; r++) {
    for(c = 0; c < mat->cols; c++) {
      free(mat->data[r][c]);
    }
    free(mat->data[r]);
  }
  free(mat->data);
  free(mat);
}

int SomeStructMat_overwrite(SomeStructMat_ptr ssm, int r, int c, SomeStruct_ptr ssp) {
  // TODO: Check that r and c are within bounds!
  somestruct_destroy(ssm->data[r][c]);
  ssm->data[r][c] = ssp;
}

void SomeStructMat_print(SomeStructMat_ptr mat) {
  int r,c;
  for(r = 0; r < mat->rows; r++) {
    for(c = 0; c < mat->cols; c++) {
      printf("[%d, %d] ", mat->data[r][c]->foo, mat->data[r][c]->bar);
    }
    printf("\n");
  }
}

int main(int argc, char** argv) {
  SomeStructMat_ptr ssm = SomeStructMat_new(2,3);

  SomeStructMat_print(ssm);

  printf("----------------\n");

  SomeStructMat_overwrite(ssm, 0, 1, somestruct_new(5,6));

  SomeStructMat_print(ssm);

  printf("----------------\n");

  SomeStructMat_destroy(ssm);

  return 0;
}

更新:要在g ++下编译,你需要转换来自malloc的void指针。像这样:

#include <cstdio>
#include <cstdlib>

typedef struct SomeStruct SomeStruct;
struct SomeStruct {
  int foo;
  int bar;
};
typedef SomeStruct* SomeStruct_ptr;
typedef struct SomeStructMat SomeStructMat;
typedef SomeStructMat* SomeStructMat_ptr;
struct SomeStructMat {
  int rows;
  int cols;
  SomeStruct_ptr** data;
};

SomeStruct_ptr somestruct_new(int foo, int bar) {
  SomeStruct_ptr ssp = (SomeStruct_ptr) malloc(sizeof(SomeStruct));
  ssp->foo = foo;
  ssp->bar = bar;
  return ssp;
}

void somestruct_destroy(SomeStruct_ptr ssp) {
  free(ssp);
}

SomeStruct_ptr** somestructmat_new(int rows, int cols) {
  int r, c;
  SomeStruct_ptr** mat = (SomeStruct_ptr**) malloc( rows * sizeof(SomeStruct_ptr*) );

  for(r = 0; r < rows; ++r) {
    mat[r] = (SomeStruct_ptr*) malloc(sizeof(SomeStruct_ptr) * cols);
    for(c = 0; c < cols; ++c) {
      mat[r][c] = somestruct_new(0,0);
    }
  }
  return mat;
}

SomeStructMat_ptr SomeStructMat_new(int rows, int cols) {
  SomeStructMat_ptr mat = (SomeStructMat_ptr) malloc(sizeof(SomeStructMat));
  mat->rows = rows;
  mat->cols = cols;
  mat->data = somestructmat_new(rows, cols); 
  return mat;
}

void SomeStructMat_destroy(SomeStructMat_ptr mat) {
  int r,c;
  for(r = 0; r < mat->rows; r++) {
    for(c = 0; c < mat->cols; c++) {
      free(mat->data[r][c]);
    }
    free(mat->data[r]);
  }
  free(mat->data);
  free(mat);
}

int SomeStructMat_overwrite(SomeStructMat_ptr ssm, int r, int c, SomeStruct_ptr ssp) {
  // TODO: Check that r and c are within bounds!
  somestruct_destroy(ssm->data[r][c]);
  ssm->data[r][c] = ssp;
}

void SomeStructMat_print(SomeStructMat_ptr mat) {
  int r,c;
  for(r = 0; r < mat->rows; r++) {
    for(c = 0; c < mat->cols; c++) {
      printf("[%d, %d] ", mat->data[r][c]->foo, mat->data[r][c]->bar);
    }
    printf("\n");
  }
}

int main(int argc, char** argv) {
  SomeStructMat_ptr ssm = SomeStructMat_new(2,3);

  SomeStructMat_print(ssm);

  printf("----------------\n");

  SomeStructMat_overwrite(ssm, 0, 1, somestruct_new(5,6));

  SomeStructMat_print(ssm);

  printf("----------------\n");

  SomeStructMat_destroy(ssm);

  return 0;
}