我是C的完整菜鸟(<1周),我正在努力掌握如何处理它,虽然我熟悉其他语言的编程.作为第一个目标,我想编写一个函数来对矩阵进行高斯减少.我对算法没有任何问题,但事实证明我不知道如何表示矩阵.为简单起见,我假设我们使用float条目.
第一种天真的方式是使用像数组一样的数组
float naifMatrix[3][3] = {
{2, 1, 3},
{0, -1, 4},
{1, 3, 0}
};
Run Code Online (Sandbox Code Playgroud)
问题是你不能在不知道先验维度的情况下将这样的对象作为参数传递(当然我希望能够使用任意大小的矩阵,这在编译时是未知的).在使用向量并将它们表示为数组时,人们不会看到这个问题.如果我做
float vector[3] = {1, 2, 3};
norm(vector);
Run Code Online (Sandbox Code Playgroud)
它会工作,提供我宣布norm样
norm(float * vector);
Run Code Online (Sandbox Code Playgroud)
当vector通过时,它被转换成&vector[0],并没有太大的信息丢失(基本上一个必须跟踪长度).但我不能只是打电话
gaussReduction(naifMatrix);
Run Code Online (Sandbox Code Playgroud)
并宣布gaussReduction与
gaussReduction(float ** naifMatrix);
Run Code Online (Sandbox Code Playgroud)
因为naifMatrix被转换(并且正确地)转换为指向浮点数组的指针,而不是指向指针的指针.由于我不知道这个数组有多大,我没有看到声明的方法gaussReduction.
当然我可以通过将指针传递给void来作弊,但在解除引用之前,我需要将它转换为正确的类型(float[3] *),这也是我不知道的先验.此外,在我看来,滥用void *一个失败的目的之一是使用C而不是其他语言,这是一种严格的类型检查.
到目前为止,我发现的最佳解决方案是使用结构.矩阵基本上由其条目列表和两个维度给出.所以我能做到
struct matrix {
float * begin;
int rows, columns;
};
Run Code Online (Sandbox Code Playgroud)
并用它作为
struct matrix matrix = {&naifMatrix[0], 3, 3};
Run Code Online (Sandbox Code Playgroud)
问题是这仍然很烦人.首先,struct matrix从双数组中获取a是很难的,第二个必须明确地给出维数.我很乐意用一种"构造函数"函数来包装它,比如
struct matrix matrix = Matrix(naifMatrix);
Run Code Online (Sandbox Code Playgroud)
但出于两个原因我不能这样做.首先,我将上述相同的问题naifMatrix作为参数传递给函数.其次,即使我可以通过它,我也会得到一个指针,因此我无法获得有关尺寸的信息(在这种情况下,两者都是3).
是否有更合理的方法来传递和操纵矩阵的基准?
C99在语言中添加了可变长度数组:
_Bool gaussReduction(size_t rows, size_t cols, float matrix[rows][cols]);
Run Code Online (Sandbox Code Playgroud)
如果你有定义
float naifMatrix[3][3] = {
{2, 1, 3},
{0, -1, 4},
{1, 3, 0}
};
Run Code Online (Sandbox Code Playgroud)
你可以通过尺寸获得
size_t rows = sizeof naifMatrix / sizeof *naifMatrix;
size_t cols = sizeof *naifMatrix / sizeof **naifMatrix;
Run Code Online (Sandbox Code Playgroud)
您可以使用宏来最小化重复.运用
#define rowsof(MATRIX) (sizeof (MATRIX) / sizeof *(MATRIX))
#define colsof(MATRIX) (sizeof *(MATRIX) / sizeof **(MATRIX))
#define matrixarg(MATRIX) rowsof(MATRIX), colsof(MATRIX), (MATRIX)
Run Code Online (Sandbox Code Playgroud)
你最终会得到
gaussReduction(matrixarg(naifMatrix));
Run Code Online (Sandbox Code Playgroud)
或者,使用复合文字而不是变量
gaussReduction(matrixarg(((float [3][3]){
{2, 1, 3},
{0, -1, 4},
{1, 3, 0}
})));
Run Code Online (Sandbox Code Playgroud)
使用可变长度数组具有与等效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];
Run Code Online (Sandbox Code Playgroud)