c - C中结构中的二维数组

标签 c multidimensional-array c99 flexible-array-member

我试图在一个结构中初始化一个二维数组,但我总是得到一个错误:

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/

相关文章:

c - 如何在c中的文本文件中获取空行?

c - 从文本文件中读取第一个单词,找出它的长度并计算文件中有多少个该长度的单词

c - 指向一个结构内的数组,该结构位于另一个结构内

c - 每次将复合文字分配给循环中的指针时是否都会创建一个新对象?

c - 如何定义外部变量和声明?

c - 如何编译 GCC 生成的 asm?

php - php中删除数组中的一些数据

php - 计算多维关联数组中的项目

python - SciPy 中的二维积分

c - 为什么 strcpy 上没有段错误?