我试图在一个结构中初始化一个二维数组,但我总是得到一个错误:
gcc -g -Wall -W -I/usr/include/SDL -c -o fractal.o fractal.c
In file included from fractal.c:2:0:
fractal.h:12:12: error: array type has incomplete element type ‘double[]’
double values[][];
代码如下:
struct fractal {
char name[64];
int height;
int width;
double a;
double b;
double meanValue;
double values[][]; /*This line is causing the error*/
};
理想情况下,我想像这样初始化二维数组的高度和宽度:
struct fractal {
/*... Same code as above ...*/
double values[width][height];
};
但是我在编译时遇到了另外两个错误:
gcc -g -Wall -W -I/usr/include/SDL -c -o fractal.o fractal.c
In file included from fractal.c:2:0:
fractal.h:12:19: error: ‘width’ undeclared here (not in a function)
double values[width][height];
^
fractal.h:12:26: error: ‘height’ undeclared here (not in a function)
double values[width][height];
^
我到处查看,但我的代码应该可以工作,但我不明白为什么不行。
感谢帮助
最佳答案
作为免责声明,这是一个高级主题,因此如果您是初学者,您可能想要完全放弃它并使用 double*
。数组后跟对每个指针的 malloc 调用。 (适合初学者,专业代码 Not Acceptable 。)
这是一个高级主题,因为这种特殊情况是 C 中的一个弱点。您尝试使用的功能(结构末尾有一个空数组)被称为灵活数组成员 .然而,这只适用于一维。如果在编译时这两个维度都未知,则您必须想出一个变通办法。
分配部分与任何灵活的数组成员一样:动态分配结构并为尾随数组确定大小。
fractal_t* f = malloc(sizeof *f + sizeof(double[height][width]) );
(在这种情况下利用方便的 VLA 语法,尽管灵活的数组成员不是 VLA。)
从技术上讲,该结构的最后一个成员应该是 double[]
现在,或者说结构声明。但是 malloc 返回的内存在您访问它之前没有实际的有效类型,之后该内存的有效类型成为用于访问的类型。
我们可以使用此规则来访问该内存,就好像它是 double[][]
,即使结构中的指针类型不同。给定一个分形 f
,通过指针访问的代码变成了这样:
double (*array_2D)[width] = (double(*)[width]) f->values;
在哪里array_2D
是一个数组指针。此处使用的最正确的类型应该是指向 double 组的数组指针,double (*)[height][width]
,但是那个带有强制性的丑陋访问 (*array_2D)[i][j]
.为了避免这种丑陋,一个常见的技巧是在数组指针声明中省略最左边的维度,然后我们可以通过 array_2D[i][j]
访问它。看起来更漂亮。
示例代码:
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
char name[64];
size_t height;
size_t width;
double a;
double b;
double meanValue;
double values[];
} fractal_t;
fractal_t* fractal_create (size_t height, size_t width)
{
// using calloc since it conveniently fills everything with zeroes
fractal_t* f = calloc(1, sizeof *f + sizeof(double[height][width]) );
f->height = height;
f->width = width;
// ...
return f;
}
void fractal_destroy (fractal_t* f)
{
free(f);
}
void fractal_fill (fractal_t* f)
{
double (*array_2D)[f->width] = (double(*)[f->width]) f->values;
for(size_t height=0; height < f->height; height++)
{
for(size_t width=0; width < f->width; width++)
{
array_2D[height][width] = (double)width; // whatever value that makes sense
}
}
}
void fractal_print (const fractal_t* f)
{
double (*array_2D)[f->width] = (double(*)[f->width]) f->values;
for(size_t height=0; height < f->height; height++)
{
for(size_t width=0; width < f->width; width++)
{
printf("%.5f ", array_2D[height][width]);
}
printf("\n");
}
}
int main (void)
{
int h = 3;
int w = 4;
fractal_t* fractal = fractal_create(h, w);
fractal_fill(fractal); // fill with some garbage value
fractal_print(fractal);
fractal_destroy(fractal);
}
关于c - C中结构中的二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49879219/