如何在堆上创建可变长度数组?

时间:2016-11-28 20:09:50

标签: c dynamic-memory-allocation calloc variable-length-array

我使用C&C的可变长度数组来实现算法:

$search.Name -contains "$($VM_NAME).vhdx"

我设法测试这确实失败了荒谬的尺寸。有没有办法在堆而不是堆栈上分配这个矩阵?否则,我必须将其重写为int matrix[rows][cols]; ...

int**这样的东西?请注意,关于可变长度数组,此问题具体

2 个答案:

答案 0 :(得分:2)

看起来很简单。唯一远程棘手的位是保持指向动态分配的数组的指针的类型:

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

static void print_matrix(int r, int c, int matrix[r][c])
{
    for (int i = 0; i < r; i++)
    {
        for (int j = 0; j < c; j++)
            printf(" %d", matrix[i][j]);
        putchar('\n');
    }
}

static void set_matrix(int r, int c, int matrix[r][c])
{
    for (int i = 0; i < r; i++)
    {
        for (int j = 0; j < c; j++)
            matrix[i][j] = (i+1) * 100 + j + 1;
    }
}

int main(void)
{
    size_t rows = 9;
    size_t cols = 7;
    size_t size = sizeof(int[rows][cols]);
    printf("rows = %zu, cols = %zu, size = %zu\n", rows, cols, size);
    int (*matrix)[cols] = calloc(sizeof(int[rows][cols]), 1);
    if (matrix != 0)
    {
        set_matrix(rows, cols, matrix);
        print_matrix(rows, cols, matrix);
        free(matrix);
    }
    return 0;
}

此代码小心地使用calloc()将数组的所有元素归零,然后调用set_matrix()将它们设置为非零值。如上所述,malloc()会优于calloc(),但使用的问题为calloc(),并且使用此代码也很难(例如,条件赋值)在set_matrix()中,例如if (i && j && i != j))。

示例输出:

rows = 9, cols = 7, size = 252
 101 102 103 104 105 106 107
 201 202 203 204 205 206 207
 301 302 303 304 305 306 307
 401 402 403 404 405 406 407
 501 502 503 504 505 506 507
 601 602 603 604 605 606 607
 701 702 703 704 705 706 707
 801 802 803 804 805 806 807
 901 902 903 904 905 906 907

答案 1 :(得分:1)

您可以创建指向VLA的指针:

size_t rows, cols;
... // get values for rows and cols
T (*arr)[cols] = malloc( sizeof (T [cols]) * rows );
if ( arr )
{
  ...
  arr[i][j] = some_value; 
  ...
}

关于是否

存在争议
T (*arr)[cols] = malloc( sizeof *arr * rows );

应该有效。标准的措辞方式,此表单会导致未定义的行为,因为sizeof必须在运行时评估*arr(因为表达式 *arr指的是VLA ),arr是评估sizeof *arr时的无效指针。

但是,这取决于“评估”在特定背景下的含义;没有理由必须取消引用 arr才能确定它所指向的数组的大小,比固定长度数组更多:

T (*arr)[10] = malloc( sizeof *arr * rows ); 

我和其他一些人认为标准在这方面措辞不佳,而且sizeof *arr应该有效arr是否指向固定的可变长度数组。这是我使用的成语,它并没有让我失望......

但是,如果我没有指出这个问题,我将会失职,并为你提供一些我知道不会导致UB的东西。