我需要执行此操作,以保持对矩阵的操作。这是否意味着它需要通过引用传递?
这样就足够了吗?
void operate_on_matrix(char matrix[][20]);
Answers:
C确实没有多维数组,但是有几种模拟它们的方法。将此类数组传递给函数的方式取决于模拟多维的方式:
1)使用数组数组。仅当在编译时完全确定了数组边界,或者您的编译器支持VLA时,才可以使用此方法:
#define ROWS 4
#define COLS 5
void func(int array[ROWS][COLS])
{
int i, j;
for (i=0; i<ROWS; i++)
{
for (j=0; j<COLS; j++)
{
array[i][j] = i*j;
}
}
}
void func_vla(int rows, int cols, int array[rows][cols])
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int x[ROWS][COLS];
func(x);
func_vla(ROWS, COLS, x);
}
2)使用(动态分配的)数组指针指向(动态分配的)数组。通常在运行时才知道数组范围时使用。
void func(int** array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}
int main()
{
int rows, cols, i;
int **x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * sizeof *x);
for (i=0; i<rows; i++)
{
x[i] = malloc(cols * sizeof *x[i]);
}
/* use the array */
func(x, rows, cols);
/* deallocate the array */
for (i=0; i<rows; i++)
{
free(x[i]);
}
free(x);
}
3)使用一维数组并固定索引。这可以与静态分配(固定大小)和动态分配的数组一起使用:
void func(int* array, int rows, int cols)
{
int i, j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i*cols+j]=i*j;
}
}
}
int main()
{
int rows, cols;
int *x;
/* obtain values for rows & cols */
/* allocate the array */
x = malloc(rows * cols * sizeof *x);
/* use the array */
func(x, rows, cols);
/* deallocate the array */
free(x);
}
4)使用动态分配的VLA。相对于选项2而言,它的一个优点是只有一个内存分配。另一个是需要较少的内存,因为不需要指针数组。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern void func_vla(int rows, int cols, int array[rows][cols]);
extern void get_rows_cols(int *rows, int *cols);
extern void dump_array(const char *tag, int rows, int cols, int array[rows][cols]);
void func_vla(int rows, int cols, int array[rows][cols])
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = (i + 1) * (j + 1);
}
}
}
int main(void)
{
int rows, cols;
get_rows_cols(&rows, &cols);
int (*array)[cols] = malloc(rows * cols * sizeof(array[0][0]));
/* error check omitted */
func_vla(rows, cols, array);
dump_array("After initialization", rows, cols, array);
free(array);
return 0;
}
void dump_array(const char *tag, int rows, int cols, int array[rows][cols])
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4d", array[i][j]);
putchar('\n');
}
}
void get_rows_cols(int *rows, int *cols)
{
srand(time(0)); // Only acceptable because it is called once
*rows = 5 + rand() % 10;
*cols = 3 + rand() % 12;
}
(请参阅srand()
-为什么只调用一次?。)
void func_vla(int array[rows][cols], int rows, int cols)
应该是void func_vla(int rows, int cols, int array[rows][cols])
__STDC_NO_VLA__
。如果编译器不支持VLA,则当然不会编译。
我不知道您所说的“数据不丢失”是什么意思。这是将普通2D数组传递给函数的方法:
void myfunc(int arr[M][N]) { // M is optional, but N is required
..
}
int main() {
int somearr[M][N];
...
myfunc(somearr);
...
}
int (*)[N]
。这就是为什么必须提供除最外层尺寸之外的所有尺寸的原因-阵列仅衰减一次。这绝对与“计算机需要知道的”无关-废话。将其与1D情况进行比较:void func (int [n])
,它会进行调整,void func (int*)
并且所有大小信息都会丢失-“计算机”一无所知,编译器也不会在意。
对于C和C ++,最干净的技术是:像2D数组一样传递1D数组,然后在函数内部用作2D。
#include <stdio.h>
void func(int row, int col, int* matrix){
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
printf("%d ", *(matrix + i*col + j)); // or better: printf("%d ", *matrix++);
}
printf("\n");
}
}
int main(){
int matrix[2][3] = { {0, 1, 2}, {3, 4, 5} };
func(2, 3, matrix[0]);
return 0;
}
在内部,无论数组有多少维,C / C ++始终维护一维数组。因此,我们可以像这样传递任何多维数组。
func(2, 3, matrix)
,那么我们应该有void func(int row, int col, int** matrix)
?
int*[3]
为int**
,大多数C / C ++编译器可能不允许这样做。
int matrix[2][2]
,占用4个“单元”的内存,因此从*(p)
到*(p+3)
(其中p是第一个元素的地址)在分配的内存范围内。这个答案也一样。您发布的线程是关于取消引用数组中最后一个元素之后的元素,在此情况下并非如此。@Minhas Kamal提供的答案绝对安全,只要您在raw
和中通过合法边界即可col
。