【问题标题】:Initialize two dimensional array with variable size in visual studio 2017在 Visual Studio 2017 中初始化可变大小的二维数组
【发布时间】:2021-06-20 19:24:08
【问题描述】:

我想在 Visual Studio 2017 c 中初始化一个可变大小的二维数组。它是一个具有整数维数的简单正方形。但是我得到以下错误缺少下标并且无法分配常量大小为 0 的数组。

int dim = 10;
short square [dim][dim];

使用 malloc 不能像以前那样使用二维,这意味着其余代码不再起作用,在 Visual Studio 2017 中仍然使用具有可变大小的二维数组的最佳解决方案是什么?

int *arr = (int *)malloc(row * col * sizeof(int)); 

【问题讨论】:

  • short square [10][10]; 可以在任何编译器中工作。
  • 你的 malloc 不是你分配二维数组的方式
  • MSVC 不支持 VLA。
  • MSVC 不支持 VLA,以后也不打算支持 VLA。最好的解决方案可能是分配一个一维数组并自己进行索引计算。
  • 我会选择short (*square)[dim] = malloc(dim * sizeof *square);,但我不确定 MSVC 是否接受。

标签: c visual-studio-2017


【解决方案1】:

int *arr = (int *)malloc(row * col * sizeof(int));你已经得到了正确的分配部分(尽管你可以放弃演员表)。现在只需像这样访问成员:

for(size_t i=0; i<row; i++)
  for(size_t j=0; j<col; j++)
    arr[i*col + j] = ... ;

这有时被称为“错位二维数组”,在 1999 年“可变长度数组”标准化之前,这种数组在 1990 年代就被使用了。

请注意,指针对指针的解决方案不必要地低效且复杂。有关详细信息,请参阅Correctly allocating multi-dimensional arrays(尽管该帖子使用现代标准 C 和 VLA,因此示例无法在 MSVC 中编译)。

【讨论】:

    【解决方案2】:

    我想在 Visual Studio 2017 c 中初始化一个可变大小的二维数组。

    我听说微软最新的 C 编译器支持可变长度数组,或者可能是即将推出的。在 C11 和 C17 中对它们的支持是可选的,但是,从历史上看,Microsoft 编译器已经忽略了这种支持。即使在 C99(其中 VLA 支持是强制性的)是当前标准时也是如此。因此,MSVC 2017 拒绝您的 VLA 声明也就不足为奇了。

    使用 malloc 不能像以前那样使用二维,这意味着其余代码不再起作用,

    可以通过malloc分配一个二维数组,这样就可以作为二维数组访问,但是

    • 您的示例指针声明和分配没有正确的格式,并且
    • 没有 VLA 支持,您仍然需要为第二个维度声明一个常量大小。

    在 Visual Studio 2017 中仍然使用可变大小的二维数组的最佳解决方案是什么?

    如果 VS 2017 不接受问题中提供的代码,那么它不提供任何机制来声明在运行时确定两个维度的二维数组。那么你的一些更好的选择是:

    • 选择支持的数组大小的上限,并将其声明为具有该大小。在任何给定的运行中,只使用您需要的部分。

    • 声明并动态分配一个指针数组,该数组将用作指向数组行的指针。分别为每一行动态分配空间。生成的数据结构在内存中的布局与真正二维数组的布局不同,但可以通过与 one 相同的语法进行访问。

    • 如问题所示执行动态分配,并在此基础上模拟二维数组。在这种情况下,编写一个或多个宏来包装地址/偏移逻辑可能会有所帮助。

    【讨论】:

      【解决方案3】:

      如果 MSVC 不支持 VLA,但您的代码希望将 arr 索引为 arr[i][j],那么您将获得创意。

      如果您的数组内容需要是连续的,那么您需要分配一个后备存储:

      int *store = malloc( dim * dim * sizeof *store );
      

      然后将arr 作为指针数组分配到该存储中:

      int **arr = malloc( dim * sizeof *arr );
      
      for ( size_t i = 0; i < dim; i++ )
        arr[i] = store + i * dim;
      

      这给了我们这样的东西:

           int **      int *                  int
           +---+      +---+                   +---+
      arr: |   | ---> |   | arr[0] ---------> |   | arr[0][0]  (store[0])
           +---+      +---+                   +---+
                      |   | arr[1] -------+   |   | arr[0][1]  (store[1])
                      +---+               |   +---+
                       ...                |    ...
                      +---+               |   +---+
                      |   | arr[dim-1] -+ |   |   | arr[0][dim-1] (store[dim-1])
                      +---+             | |   +---+
                                        | +-> |   | arr[1][0] (store[dim])
                                        |     +---+
                                        |     |   | arr[1][1] (store[dim+1])
                                        |     +---+
                                        |      ...
                                        |     +---+
                                        |     |   | arr[1][dim-1] (store[dim+dim-1])
                                        |     +---+
                                        |      ...
                                        |     +---+
                                        +---> |   | arr[dim-1][0] (store[dim*(dim-1)])
                                              +---+
                                              |   | arr[dim-1][1] (store[dim*(dim-1)+1]
                                              +---+
        
           
      

      如果你的数组不需要是连续的,你可以做一个“锯齿状”分配:

      int **arr = malloc( dim * sizeof *arr ); // allocates your "columns"
      if ( arr )
      {
        size_t i;
        for ( i = 0; i < dim; i++ )
        {
          arr[i] = malloc( dim * sizeof *arr[i] ); // allocates your "rows"
        }
      }
      

      arr 是指向int *dim 元素数组的指针,每个arr[i] 都是指向dim 元素数组int 的指针,给你这样的东西:

           int **      int *                      int
           +---+       +---+                      +---+
      arr: |   | ----> |   | arr[0] ------------> |   | arr[0][0]
           +---+       +---+                      +---+
                       |   | arr[1] ----------+   |   | arr[0][1]
                       +---+                  |   +---+
                        ...                   |    ...
                                              |   
                                              |   +---+
                                              +-> |   | arr[1][0]
                                                  +---+
                                                  |   | arr[1][1]
                                                  +---+
                                                   ...
      

      请注意,如果您将arr 传递给任何函数,则相应的函数参数必须具有int ** 类型,而不是int (*)[dim]int [][dim]int [dim][dim]

      【讨论】:

      • 使用指向指针的指针是实现二维数组的一种低效方式,在大多数情况下不建议使用。它唯一的好处是允许x[i][j] 语法而不是计算索引或辅助函数或宏,但这对程序员来说是一个小好处,学生应该学会把事情做好,即使他们需要更多的努力部分。
      • 另外,该决定与内存是否需要连续无关。指针对指针方法不需要非连续内存。它可以简单地通过为所有元素分配一个块并适当地设置各种指针来实现,这更好,因为它减少了分配和释放并使用更少的内存(因为内存管理器需要跟踪的块更少)。跨度>
      【解决方案4】:

      为此使用指向数组的指针:

      void foo(size_t rows, size_t cols)
      {
          int (*array)[cols] = malloc(rows * sizeof(*array));
          int (*array1)[rows][cols] = malloc(sizeof(*array));
      }
      

      【讨论】:

      • 这仍然依赖于 VLA 支持。
      • @JohnBollinger 我错过了关于这个 MS 废话的内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-23
      • 2018-03-04
      • 2014-09-28
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多