带指针的多维数组元素赋值
Multidimensional array element assignment with pointer
我有一个参差不齐的二维结构数组和一个分配函数 return 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
很大,数组的维度也很大。
*(arr[i][j]) = foo();
会将二维数组中指向结构的指针的值设置为指向 foo 返回的结构的指针,如果这是您真正想要的。
如果您只想保留指向结构的二维指针数组,那么您可以将数组声明更改为 mystruct* arr[3][4]
并使用 arr[i][j] = foo()
.
如果您真的希望 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.
如果您不需要每行分配一次,并且您很乐意用 void bar(mystruct *p)
构造 mystruct
并使用指向某个已分配存储的指针调用,那么您的数组可以存储 mystruct
直接对象:
mystruct (*arr)[cols] = malloc( rows * sizeof *arr );
for ( int i = 0; i < rows; ++i )
bar( &arr[i][0] );
我认为在这种情况下使用一些抽象会有所帮助。我匆忙写了下面的例子,希望对你有帮助。
更新:根据评论修改。仍然在 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;
}
我有一个参差不齐的二维结构数组和一个分配函数 return 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
很大,数组的维度也很大。
*(arr[i][j]) = foo();
会将二维数组中指向结构的指针的值设置为指向 foo 返回的结构的指针,如果这是您真正想要的。
如果您只想保留指向结构的二维指针数组,那么您可以将数组声明更改为 mystruct* arr[3][4]
并使用 arr[i][j] = foo()
.
如果您真的希望 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.
如果您不需要每行分配一次,并且您很乐意用 void bar(mystruct *p)
构造 mystruct
并使用指向某个已分配存储的指针调用,那么您的数组可以存储 mystruct
直接对象:
mystruct (*arr)[cols] = malloc( rows * sizeof *arr );
for ( int i = 0; i < rows; ++i )
bar( &arr[i][0] );
我认为在这种情况下使用一些抽象会有所帮助。我匆忙写了下面的例子,希望对你有帮助。
更新:根据评论修改。仍然在 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;
}