Ich muss dies tun, um auch Operationen in der Matrix beizubehalten. Bedeutet das, dass es als Referenz übergeben werden muss?
Wird das ausreichen?
void operate_on_matrix(char matrix[][20]);
Antworten:
C hat nicht wirklich mehrdimensionale Arrays, aber es gibt verschiedene Möglichkeiten, sie zu simulieren. Die Art und Weise, wie solche Arrays an eine Funktion übergeben werden, hängt von der Art und Weise ab, wie die mehreren Dimensionen simuliert werden:
1) Verwenden Sie ein Array von Arrays. Dies kann nur verwendet werden, wenn Ihre Array-Grenzen zur Kompilierungszeit vollständig festgelegt sind oder wenn Ihr Compiler VLAs unterstützt :
#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) Verwenden Sie ein (dynamisch zugewiesenes) Array von Zeigern auf (dynamisch zugewiesene) Arrays. Dies wird meistens verwendet, wenn die Array-Grenzen erst zur Laufzeit bekannt sind.
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) Verwenden Sie ein eindimensionales Array und korrigieren Sie die Indizes. Dies kann sowohl mit statisch zugewiesenen (feste Größe) als auch mit dynamisch zugewiesenen Arrays verwendet werden:
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) Verwenden Sie eine dynamisch zugewiesene VLA. Ein Vorteil gegenüber Option 2 besteht darin, dass nur eine Speicherzuordnung vorhanden ist. Zum anderen wird weniger Speicher benötigt, da das Array von Zeigern nicht benötigt wird.
#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;
}
(Siehe srand()
- warum nur einmal anrufen? )
void func_vla(int array[rows][cols], int rows, int cols)
sollte seinvoid func_vla(int rows, int cols, int array[rows][cols])
__STDC_NO_VLA__
. Wenn der Compiler keine VLAs unterstützt, wird er natürlich nicht kompiliert.
Ich weiß nicht, was Sie unter "Daten gehen nicht verloren" verstehen. So übergeben Sie ein normales 2D-Array an eine Funktion:
void myfunc(int arr[M][N]) { // M is optional, but N is required
..
}
int main() {
int somearr[M][N];
...
myfunc(somearr);
...
}
int (*)[N]
. Und deshalb müssen auch alle Dimensionen außer der äußersten angegeben werden - das Array zerfällt nur einmal. Dies hat absolut nichts mit dem zu tun, was "der Computer wissen muss" - Unsinn. Vergleichen Sie es mit dem 1D-Fall void func (int [n])
:, der angepasst wird void func (int*)
und alle Größeninformationen verloren gehen - "der Computer" erfährt nichts und der Compiler könnte es nicht weniger interessieren.
Die sauberste Technik für C und C ++ ist: Übergeben Sie ein 2D-Array wie ein 1D-Array und verwenden Sie es dann als 2D innerhalb der Funktion.
#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;
}
Unabhängig von der Anzahl der Dimensionen eines Arrays verwaltet C / C ++ intern immer ein 1D-Array. Und so können wir jedes mehrdimensionale Array wie dieses übergeben.
func(2, 3, matrix)
, sollten wir dann haben void func(int row, int col, int** matrix)
?
int*[3]
nach int**
, was für die meisten C / C ++ - Compiler möglicherweise nicht zulässig ist.
int matrix[2][2]
belegt 4 "Zellen" des Speichers, so dass von *(p)
bis *(p+3)
(wobei p eine Adresse des ersten Elements ist) innerhalb der Dimension des zugewiesenen Speichers liegen. Gleiches gilt für diese Antwort. In dem von Ihnen geposteten Thread geht es darum, ein Element nach dem letzten im Array zu dereferenzieren, was hier nicht der Fall ist. Die Antwort von @Minhas Kamal ist absolut sicher, vorausgesetzt, Sie überschreiten legitime Grenzen in raw
und col
.