C 中的可变大小矩阵

发布于 2024-08-09 16:29:18 字数 205 浏览 2 评论 0原文

有没有办法在 C (不是 C++,只是 C)中创建可变大小的双脚本数组?我知道要创建一个可变大小的单脚本数组,您只需使用一个指针,例如

float *array;
array = (float *) calloc(sizeof(float), n);

创建一个大小为 n 的浮点数的单脚本数组。我可以为双脚本数组做类似的事情吗?

Is there any way to create a variable sized doubly-scripted array in C (not C++, just C)? I know that to create a variable sized singly-scripted array, you just use a pointer, e.g.

float *array;
array = (float *) calloc(sizeof(float), n);

creates a singly-scripted array of floats of size n. Is there something similar that I can do for doubly-scripted arrays?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

じее 2024-08-16 16:29:19

我很惊讶没有人指出“明显”的替代方案,它保留主矩阵的单个连续分配,但具有给出双下标的指针向量。 (我想这意味着它并不明显。)

float **array2d = malloc(sizeof(*array2d) * height);
float  *array1d = malloc(sizeof(*array1d) * height * width);

for (i = 0; i < height; ++i)
    array2d[i] = &array1d[i * width];

现在您可以像往常一样编写二维数组访问:

array2d[0][0] = 123.0;

显然,我们还需要检查内存分配。

I'm surprised no-one has pointed out the 'obvious' alternative which preserves the single contiguous allocation for the main matrix, but has the vector of pointers to give double subscripting. (I suppose that means it isn't obvious, after all.)

float **array2d = malloc(sizeof(*array2d) * height);
float  *array1d = malloc(sizeof(*array1d) * height * width);

for (i = 0; i < height; ++i)
    array2d[i] = &array1d[i * width];

Now you can write 2-D array accesses as usual:

array2d[0][0] = 123.0;

Clearly, we also need to check the memory allocation.

寻找我们的幸福 2024-08-16 16:29:19

geeksforgeeks.com 中给出了一种更简单的方法“使用指向 VLA 第一行的指针”:

int (*arr)[col] = calloc(row, sizeof *arr);

然后您可以像这样简单地访问每个元素

arr[i][j]

There is a simpler way given in geeksforgeeks.com "Using a pointer to the first row of VLA":

int (*arr)[col] = calloc(row, sizeof *arr);

and then you can access each element simply like

arr[i][j]
鹿港巷口少年归 2024-08-16 16:29:18

C 中没有双脚本数组;只有数组的数组。例如:

int a[3][3];

应该读作“3 个整数数组的数组”,而不是“3x3 整数数组”。这从表达式的类型中可以立即看出 - 例如,a[0] 是一个有效的表达式,其类型为 int[3]

对于数组类型,数组大小是类型的一部分,因此必须在编译时知道。因此,虽然您可以使用“指向数组的指针”类型来使一维动态化,但仍然需要修复其余的维度:

int (*p)[3] // pointer to arrays of 3 ints each

有两种传统的解决方法:

  1. 只需使用 的单维动态数组width x height 元素,并根据 2D 坐标计算 1D 索引,如 (y * width + x)

  2. 使用指针到指针:

    int** a = malloc(sizeof(int*) * height);
    for (i = 0; i < height; ++i) a[i] = malloc(sizeof(int) * width);
    a[0][0] = 123;
    ...
    

    这里的问题是你的数组不再需要是矩形的,而且你不能真正强制它。从性能角度来看,它也比单个连续的内存块更差。

在C99中,还可以使用变长数组:

void foo(int width, int height) {
    int a[width][height];
    ...
}

There are no double-scripted arrays in C; there are only arrays of arrays. E.g. this:

int a[3][3];

Should read as "array of 3 arrays of 3 ints", not as "array of 3x3 ints". This is immediately visible from types of expressions - e.g. a[0] is a valid expression, and its type is int[3].

For array types, array size is part of the type, and therefore must be known at compile-time. Therefore, while you can have a type "pointer to arrays" to make one dimension dynamic, the remaining ones would still have to be fixed:

int (*p)[3] // pointer to arrays of 3 ints each

There are two traditional workarounds:

  1. Just use a single-dimensional dynamic array of width x height elements, and calculate 1D indices from 2D coordinates as (y * width + x) yourself.

  2. Use pointer to pointers:

    int** a = malloc(sizeof(int*) * height);
    for (i = 0; i < height; ++i) a[i] = malloc(sizeof(int) * width);
    a[0][0] = 123;
    ...
    

    The problem here is that your array needs not be rectangular anymore, and you can't really enforce it. Performance-wise, it's also worse than a single contiguous block of memory.

In C99, you can also use variable-length arrays:

void foo(int width, int height) {
    int a[width][height];
    ...
}
陌上青苔 2024-08-16 16:29:18

comp.lang.c FAQ对此有很好的部分。

The comp.lang.c FAQ has a good section on this.

寄与心 2024-08-16 16:29:18

对于多维数组,您几乎可以做同样的事情。

float **array;
array = calloc(sizeof(float*), n);
for(int i = 0; i < n; i++)
{
    array[i] = calloc(sizeof(float), n);
}

You can do almost the same thing for multi dimensional arrays.

float **array;
array = calloc(sizeof(float*), n);
for(int i = 0; i < n; i++)
{
    array[i] = calloc(sizeof(float), n);
}
会傲 2024-08-16 16:29:18

如果你想要一个 n 行 m 列的矩阵,那么你可以使用长度 m*n 的线性数组来表示它,其中每个索引 i 表示

row = i  / n
col = i  % n

和逆映射

i  = row * n  + col

大多数使用矩阵(如 matlab)的代数包实际上都使用这种表示形式,因为它可以很好地推广到任何维度(您也可以将其推广到 3 维矩阵)。

If you want a matrix with n rows and m columns then you can use a linear array of length m*n to represent this, where each index i represents

row = i  / n
col = i  % n

and the inverse mapping

i  = row * n  + col

Most algebra packages that use matrices like matlab actually use this representation, because it generalizes well to any dimension (you could generalize this to a 3-dimensional matrix just as well).

独自唱情﹋歌 2024-08-16 16:29:18

不,那不可能。作为替代方案,分配一个数组,并定义一个索引函数,该函数获取坐标并返回数组的索引。

int Index(int i, int j, int numCols)
{ 
    return i * numCols + j;
}

int numRows = 100;
int numCols = 200;

float *data = malloc(sizeof(float) * numRows * numCols);

data[Index(34, 56, numCols)] = 42.0f;

No, that's not possible. As an alternative, allocate a single array, and define an indexing function that takes your coordinate and returns an index into the array.

int Index(int i, int j, int numCols)
{ 
    return i * numCols + j;
}

int numRows = 100;
int numCols = 200;

float *data = malloc(sizeof(float) * numRows * numCols);

data[Index(34, 56, numCols)] = 42.0f;
青春有你 2024-08-16 16:29:18

您可以使用 C99 可变长度数组(与 gcc 一起使用):

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

void foo(size_t rows, size_t cols, float array[rows][cols])
{
    printf("%f\n", array[2][3]);
}

int main(void)
{
    size_t rows = 4;
    size_t cols = 5;
    float (*array)[cols] = calloc(sizeof (float), rows * cols);
    array[2][3] = 42;
    foo(rows, cols, array);
}

You can use C99 variable-length arrays (works with gcc):

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

void foo(size_t rows, size_t cols, float array[rows][cols])
{
    printf("%f\n", array[2][3]);
}

int main(void)
{
    size_t rows = 4;
    size_t cols = 5;
    float (*array)[cols] = calloc(sizeof (float), rows * cols);
    array[2][3] = 42;
    foo(rows, cols, array);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文