C89中作为函数参数的矩阵

问题描述 投票:3回答:3

在我大部分的本科C编程课程中,我们学习了C99,而我们的讲师从未费心告诉我们C99与以前版本之间的主要区别。

我们最近被告知,有可能在下一次考试时会要求我们使用C89实施解决方案。

我的问题是关于在函数内部声明和使用可变长度多维数组的问题。

在C99中,我可以具有这样的功能:

void func(int cols, int mat[][cols], int rows);

而在C89中,VLA和类似的装置是非法的。有人告诉我,您将需要使用一个指向指针的指针。所以像:

void func(int **mat, int cols, int rows);

但是,我在理解上有问题:

  1. 您如何在函数内部的此矩阵中访问元素。您仍然可以使用mat[i][j]表示法吗?
  2. 如何声明和填充这样的矩阵。您是否从int **mat;之类的东西开始?我以为您必须使用malloc(),但是我很难弄清楚确切的声明语句。
  3. 甚至可以像使用指针一样使用矩阵吗?我已经读过它们的工作原理类似,但不完全相同。您如何解决C89中概述的问题?

旁题。仍然关于可变大小的矩阵,有人告诉我设置如下:

int rows, cols;

// get rows and cols from stdinput

int mat[rows][cols];

由于在程序堆栈上进行了分配,因此不是创建具有给定尺寸的矩阵的最佳方法。有什么更好的方法?

谢谢!

c matrix c89 variable-length-array
3个回答
3
投票

但是,我在理解上有问题:

  1. 您如何在函数内部的此矩阵中访问元素。您还可以使用符号mat [i] [j]吗?
  2. 如何声明和填充这样的矩阵。您是从int ** mat;之类的东西开始的吗?我认为您必须使用malloc(),但我很难弄清楚确切的声明声明。
  3. 甚至可以像使用指针一样使用矩阵吗?我已经读过它们的工作原理类似,但不完全相同。怎么做您解决了C89中概述的问题?

1。 mat[i][j]

在C89中,您是正确的,除非非标准编译器扩展提供了此支持,否则您不支持VLA(gcc这样做)。但是,您可以在两个不同的数组中完成相同的操作。

如果知道columns的数目,则可以在编译时定义该值的常量,然后可以声明pointer-to-array [COLS]] >>。例如,如果您知道将有32列且行数未知,则可以执行以下操作:

#define COLS 32
...
    int (*array)[COLS] = malloc (rows * sizeof *array);

将在单个调用中分配一块内存,为rowsint[32]数组提供存储,使您可以像以前一样以array[i][j]的身份访问。使用pointer-to-array

的好处在于,您可以进行单分配和单分配。您可以根据需要realloc行数。

您的另一个选择是声明pointer-to-pointer-to

type(例如int **array;)。注意这里没有涉及数组,它只是一个指向类型的指针。这里的分配过程分为两步。您首先为一定数量的pointers(行数的指针)分配内存。例如:
int **array = malloc (rows * sizeof *array);

上面您分配了一个能够容纳rowspointers

的内存块,然后您可以分别为其分配和分配一个内存块来容纳任意数量的整数值(不需要每个行点到具有相同数量整数值的块中–由于缺少更好的单词,因此可以使用“锯齿状数组”)然后为integers values(或您使用的任何类型)分配存储空间,请执行以下操作:
for (int i = 0; i < rows; i++)
    array[i] = malloc (cols * sizeof *array[i]);

[note:

您必须验证每个分配,为简洁起见,已省略。另外请注意,在以上两种情况下,dereferenced指针都已用于设置类型大小进行分配,例如malloc (rows * sizeof *array)可能是malloc (rows * sizeof(int*)))。如果您始终使用dereferenced指针来设置typesize,则永远不会弄错类型大小)

[此时,您有一个指向存储rows数量的指针的内存块的指针,然后分配了一个内存块,该内存块能够保存cols数量的整数值,您可以将其作为array[i][j]进行访问。此外,您可以在此处realloc提供rows指针的内存块,以便在需要时随时添加行,但是您还必须为整数值分配存储空间,并在尝试执行以下操作之前将这些已分配的块分配给新的行指针在那里存储值。

当您完成基于pointer-to-pointer

的模拟2D数组时,您也可以自由使用两步。您必须先释放分配的存储整数的块,然后再释放包含行指针的块,例如
for (int i = 0; i < rows; i++)
    free (array[i]);                /* free storage for integers */
free (array);                       /* free pointers */

2。填充任何一个对象

无论哪种情况,因为您都可以使用array[i][j]表示法访问模拟2D数组,所以现在可以像在C99 +下使用2D VLA一样填充和访问array中的值。

3。矩阵可以与指向指针的指针一起使用吗

是的,模拟的2D阵列提供与上述功能完全相同的功能。


2
投票
  1. 您如何在函数内部的此矩阵中访问元素。您仍然可以使用mat[i][j]表示法吗?

1
投票

在C89中,如果您具有类似void func(int **mat, int cols, int rows)的函数,则按以下方式寻址元素,但是,单个指针就足够了

© www.soinside.com 2019 - 2024. All rights reserved.