矩阵的结构

时间:2011-01-18 12:53:40

标签: c matrix

我是C的完整菜鸟(<1周),我正在努力掌握如何使用它,虽然我熟悉其他语言的编程。作为第一个目标,我想编写一个函数来对矩阵进行高斯减少。我对算法没有任何问题,但事实证明我不知道如何表示矩阵。为简单起见,我假设我们使用float条目。

第一种天真的方式是使用像

这样的数组
float naifMatrix[3][3] = {
    {2, 1, 3},
    {0, -1, 4},
    {1, 3, 0}
};

问题在于,如果不先验地知道维度,就不能将这样的对象作为参数传递(当然我希望能够使用任意大小的矩阵,这在编译时是未知的)。在使用向量并将它们表示为数组时,人们不会看到这个问题。如果我做

float vector[3] = {1, 2, 3};
norm(vector);

只要我声明norm喜欢

,它就会奏效
norm(float * vector);

当传递vector时,它会转换为&vector[0],并且丢失的信息不多(基本上必须跟踪长度)。但我不能只打电话

gaussReduction(naifMatrix);

并使用

声明gaussReduction
gaussReduction(float ** naifMatrix);

因为naifMatrix被转换(并且正确地)到指向浮点数组的指针,而不是指向指针的指针。由于我不知道这个数组有多大,我没有办法宣布gaussReduction

当然我可以通过将指针传递给void来作弊,但在解除引用之前,我需要将其转换为正确的类型(float[3] *),这也是我不知道的先验。此外,在我看来,滥用void *一个失败了使用C而不是其他语言的目的之一,这是一种严格的类型检查。

到目前为止,我发现的最佳解决方案是使用结构。矩阵基本上由其条目列表和两个维度给出。所以我可以做到

struct matrix {
    float * begin;
    int rows, columns;
};

并将其用作

struct matrix matrix = {&naifMatrix[0], 3, 3};

问题是这仍然很烦人。首先,从双数组中获取struct matrix是很难的,第二个必须明确地给出维度。我很乐意用一种“构造函数”函数来包装它,比如

struct matrix matrix = Matrix(naifMatrix);

但出于两个原因我无法做到这一点。首先,我将naifMatrix作为参数传递给函数时遇到与上述相同的问题。其次,即使我可以通过它,我也会得到一个指针,因此我无法获得有关维度的信息(在这种情况下,两者都是3)。

是否有更合理的方法来传递和操纵矩阵的基准?

2 个答案:

答案 0 :(得分:6)

C99在语言中添加了可变长度数组:

_Bool gaussReduction(size_t rows, size_t cols, float matrix[rows][cols]);

如果您有定义

float naifMatrix[3][3] = {
    {2, 1, 3},
    {0, -1, 4},
    {1, 3, 0}
};

您可以通过

获取尺寸
size_t rows = sizeof naifMatrix / sizeof *naifMatrix;
size_t cols = sizeof *naifMatrix / sizeof **naifMatrix;

您可以使用宏来尽量减少重复。使用

#define rowsof(MATRIX) (sizeof (MATRIX) / sizeof *(MATRIX))
#define colsof(MATRIX) (sizeof *(MATRIX) / sizeof **(MATRIX))
#define matrixarg(MATRIX) rowsof(MATRIX), colsof(MATRIX), (MATRIX)

你最终会

gaussReduction(matrixarg(naifMatrix));

或使用复合文字而不是变量,

gaussReduction(matrixarg(((float [3][3]){ 
    {2, 1, 3},
    {0, -1, 4},
    {1, 3, 0}
})));

使用可变长度数组具有与等效C90代码相同的性能特征 - 您唯一能获得的是更好的语法:

// C99:
_Bool gaussReduction(size_t rows, size_t cols, float matrix[rows][cols])
{
    // size_t i = ..., j = ...
    float x = matrix[i][j];

/* C90: */
int gaussReduction(size_t rows, size_t cols, float *matrix)
{
    /* size_t i = ..., j = ... */
    float x = matrix[i * cols + j];

答案 1 :(得分:-1)

如果你这样定义:

float naifMatrix[][] = {
    {2, 1, 3},
    {0, -1, 4},
    {1, 3, 0}
};

你应该有一个指针数组的指针。然后你可以使用

gaussReduction(float ** naifMatrix);

我的C生锈了。