# C - Mehrdimensionales Array als Rückgabewert



## ZodiacXP (7. Juli 2009)

Zwei Arrays (Matrizen) werden übergeben und am Ende soll ein mehrdimensionales Array (Matrix) ausgegeben werden. Jedoch habe ich Probleme damit das Array da raus zu kriegen.

Dies ist mein Versuch:

```
// Matrix multiplikation
int* MMult(int A[][3], int B[][3])
{
	// Ergebnismatrix
	int *C[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
	
	// Zeilen
	for (short i = 0; i <= 2; i++)
	{
		// Spalten
		for (short j = 0; j <= 2; j++)
		{
			for (short k = 0; k <= 2; k++)
			{
				C[i][j] = A[i][k] * B[k][j];
			}
		}
	}

	return C;
}
```

Der Compiler meckert: 





> Illegal return type: found 'int * (*)[3]', expected 'int *'.



Habe danach " int* MMult(int A[][3], int B[][3]) [3] " versucht aber auch ohne Erfolg.


----------



## Cromon (7. Juli 2009)

Der Rückgabewert ist in dem Falle ja auch int** und nicht int*.


----------



## ZodiacXP (7. Juli 2009)

Zu int** meckert er genau so (selbe Fehlermeldung bis auf **)

```
// Matrix multiplikation
int** MMult(int A[][3], int B[][3])
{
 etc...
```


----------



## Cromon (7. Juli 2009)

achso, falsch gelesen, deine Matrix ist ja int* [3][3], also ist der Rückgabewert int***.


----------



## Matthias Reitinger (7. Juli 2009)

Hallo ZodiacXP,

hier sind gleich mehrere Sachen falsch:

Du deklarierst C als zweidimensionales Array aus Zeigern.
Du versuchst eine Stack-Adresse zurückzugeben (führt während der Laufzeit im besten Fall zu einer Speicherschutzverletzung).
Der eigentliche Algorithmus ist falsch, hier müsstest du das = durch ein += ersetzen.

Am einfachsten wäre es, wenn du der Funktion einen int**-Zeiger übergibst, der angibt wo die Ergebnismatrix gespeichert werden soll. Damit hast du dann keine Probleme mit dem Rückgabewert mehr.

Grüße, Matthias


----------



## ZodiacXP (7. Juli 2009)

Danke, Matthias!

Das fehlende Plus-Zeichen, war schon arm.
Hab voreilig den falschen Code kopiert glaub ich. C sollte kein Pointer sein, aber deine Idee ist gut.

Werd noch schnell zur Bibo rüber und ein schönes C Buch holen. Jemand vorschläge?

Hab es nun so und werd dran basteln:

```
// Matrix multiplikation
void MMult(int A[][3], int B[][3], int **C[][3])
{
	// Zeilen
	for (short i = 0; i <= 2; i++)
	{
		// Spalten
		for (short j = 0; j <= 2; j++)
		{
			for (short k = 0; k <= 2; k++)
			{
				C[i][j] += A[i][k] * B[k][j];
			}
		}
	}

}

void main()
{
	// Einheitsmatrix
	int A[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
	int B[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
	int **C[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
	MMult(A, B, C);

	printf("%d %d %d\n", C[0][0], C[0][1], C[0][2]);
	printf("%d %d %d\n", C[1][0], C[1][1], C[1][2]);
	printf("%d %d %d\n", C[2][0], C[2][1], C[2][2]);
}
```

Mit ganz komischen Ergebnis:

```
4 0 0
0 4 0
0 0 4
```


----------



## deepthroat (7. Juli 2009)

Hi.





ZodiacXP hat gesagt.:


> Werd noch schnell zur Bibo rüber und ein schönes C Buch holen. Jemand vorschläge?


Auf jeden Fall eine gute Idee. Leider kann ich dir ad hoc keins empfehlen, aber optimal wäre eins welches den C99 Standard behandelt oder wenigstens C89 (main muß int zurückgeben!).



ZodiacXP hat gesagt.:


> Mit ganz komischen Ergebnis:
> 
> ```
> 4 0 0
> ...


Arrays werden intern lediglich als Zeiger behandelt. Du hast dort als dritten Parameter ein Array von Zeigern auf Zeiger auf int deklariert. Das macht natürlich eher wenig Sinn.

Du kannst es einfach so machen:

```
void MMult(int A[][3], int B[][3], int C[][3]) {
   ...
}

int C[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
MMult(A, B, C);
```
Gruß


----------



## ZodiacXP (7. Juli 2009)

God damn it.

Das geht alles in Richtungen die das Problem komplizierter machen.

Ziel ist es eine Funktion / Algorithmus zu haben, so dass man z.B. A³ berechnen kann durch (jetzt kommt nicht C):

```
X = MMult(A, A);  // A² in X
X = MMult(X, A);  // A³ in X
```

Hab grad Louis, Dirk : "C, C++" geholt scheint aber bisschen C++ lastig zu sein.


----------



## Matthias Reitinger (7. Juli 2009)

ZodiacXP hat gesagt.:


> Ziel ist es eine Funktion / Algorithmus zu haben, so dass man z.B. A³ berechnen kann durch (jetzt kommt nicht C):
> 
> ```
> X = MMult(A, A);  // A² in X
> ...


Das klappt doch bereits, man muss es nur etwas anders schreiben:

```
MMult(A, A, X);
MMult(X, A, X);
```


----------



## ZodiacXP (9. Juli 2009)

Matthias Reitinger hat gesagt.:


> Das klappt doch bereits, man muss es nur etwas anders schreiben:
> 
> ```
> MMult(A, A, X);
> ...



Hatte ich auch gedacht, kommt aber quatsch raus:

```
// Matrix multiplikation (C = A * B)
void MMult(int A[][3], int B[][3], int C[][3])
{
	int sum;

	// Zeilen
	for (short i = 0; i <= 2; i++)
	{
		// Spalten
		for (short j = 0; j <= 2; j++)
		{
			sum = 0;
			for (short k = 0; k <= 2; k++)
			{
				sum += A[i][k] * B[k][j];
			}
			C[i][j] = sum;
		}
	}
}

void main()
{
	int A[3][3] = {{3,5,7},{4,6,8},{1,3,4}};	// Ausgangsmatrix
	int B[3][3] = {{0,0,0},{0,0,0},{0,0,0}};	// Ergebnis

	// A^2 berechnen und ausgeben
	MMult(A, A, B);
	printf("\n       / %10d %10d %10d \\\n", B[0][0], B[0][1], B[0][2]);
	printf("A^2 = |  %10d %10d %10d  |\n", B[1][0], B[1][1], B[1][2]);
	printf("       \\ %10d %10d %10d /\n\n", B[2][0], B[2][1], B[2][2]);

	// A^3 berechnen und ausgeben
	MMult(B, A, B);
	printf("       / %10d %10d %10d \\\n", B[0][0], B[0][1], B[0][2]);
	printf("A^3 = |  %10d %10d %10d  |\n", B[1][0], B[1][1], B[1][2]);
	printf("       \\ %10d %10d %10d /\n\n", B[2][0], B[2][1], B[2][2]);

	// A^4 berechnen und ausgeben
	MMult(B, A, B);
	printf("       / %10d %10d %10d \\\n", B[0][0], B[0][1], B[0][2]);
	printf("A^4 = |  %10d %10d %10d  |\n", B[1][0], B[1][1], B[1][2]);
	printf("       \\ %10d %10d %10d /\n\n", B[2][0], B[2][1], B[2][2]);
```


```
/         36         66         89 \
A^2 = |          44         80        108  |
       \         19         35         47 /

       /        461       2968      27327 \
A^3 = |         560       3604      33184  |
       \        244       1571      14464 /

       /      40582     302699    2814974 \
A^4 = |       49280     367576    3418304  |
       \      21480     160218    1489960 /
```

Bei A^3 stimmen die Werte nicht mehr. Nimmt man eine Einheitsmatrix dann rechnet er bis zum Schluss richtig. Hier ist aber A^3 (zweite und dritte Spalte) und A^4 (komplett) falsch.

Es wäre schön wenn die ersten beiden Argumente von MMult nicht als Referenz angenommen werden, sondern neu angelegt werden (call-by-value).


----------



## Matthias Reitinger (9. Juli 2009)

ZodiacXP hat gesagt.:


> Hatte ich auch gedacht, kommt aber quatsch raus:


Stimmt natürlich, da hab ich wohl nicht mitgedacht. Bei dem Aufruf werden die Elemente von B ja überschrieben, obwohl man zur Berechnung die alten Werten brauchen würde.



ZodiacXP hat gesagt.:


> Es wäre schön wenn die ersten beiden Argumente von MMult nicht als Referenz angenommen werden, sondern neu angelegt werden (call-by-value).


Wieso wäre das schön? Ich würde einfach eine temporäre Matrix anlegen und diese nach der Mutliplikation rüberkopieren:

```
void MMult(int A[][3], int B[][3], int C[][3])
{
	int sum;
	int C_[][3] = {{0,0,0},{0,0,0},{0,0,0}};

	// Zeilen
	for (short i = 0; i <= 2; i++)
	{
		// Spalten
		for (short j = 0; j <= 2; j++)
		{
			sum = 0;
			for (short k = 0; k <= 2; k++)
			{
				sum += A[i][k] * B[k][j];
			}
			C_[i][j] = sum;
		}
	}

	for (short i = 0; i <= 2; ++i) {
		for (short j = 0; j <= 2; ++j) {
			C[i][j] = C_[i][j];
		}
	}
}
```
Grüße, Matthias


----------

