我是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)。
是否有更合理的方法来传递和操纵矩阵的基准?
答案 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生锈了。