2017-01-14 5 views
1

Warum dieser Fehler (Bild 1) passiert, wenn ich ein 2d-Array zu einer Funktion eingeben möchte?inkompatible Zeigertypen übergeben int [5] [5] an Parameter vom Typ int **

enter image description here

#include <stdio.h> 
#include <stdlib.h> 
void pr(int** a){ 
    printf("%d", a[0][0]); 
} 

int main(){ 
    int a[5][5]={{1,4,7,11,15},{2,5,8,12,19},{3,6,9,16,22},{10,13,14,17,24},{18,21,23,26,30}}; 
    pr(a); 
} 
+2

Arrays und Zeiger sind nicht identisch, und ein Zeiger auf Zeiger ist nicht dasselbe wie ein 2D-Array. Sie sollten 'void pr (int a [] [5])' oder ähnliches verwenden. –

+0

Was passiert, wenn die Funktion pr nicht geändert werden kann? – user7341005

+4

Dann müssen Sie eine andere Anordnungsstruktur in 'main()': 'int * a [] = {(int []) {1, 4, 7, 11, 15}, (int []) {2, 5, 8, 12, 19}, (int []) {3, 6, 9, 16, 22}, (int []) {10, 13, 14, 17, 24}, (int []) {18, 21 , 23, 26, 30}}; '- nicht kompiliert, damit ich einen Fehler habe. Ich benutze C99 zusammengesetzte Literale. Dies gibt Ihnen ein Array von Zeigern zu "int", aber jeder Zeiger ist auf den Anfang eines Arrays von "int". –

Antwort

5

Das Kernproblem ist, dass Arrays und Zeiger nicht identisch sind (obwohl sie eng verwandt sind), und ein 2D-Array ist kein Array von Zeigern.

Dieser Code zeigt drei Möglichkeiten, das Problem zu beheben. Das Array a0 ist Ihr Array umbenannt und neu formatiert; Das Array a ist ein Array von Zeigern, und jeder Zeiger ist ein Zeiger auf ein Array von 5 int über ein 'Compound Literal', eine Funktion, die zu C99 hinzugefügt wurde. Ich habe die Druckfunktion aktualisiert, um alle 25 Elemente des Arrays zu drucken, das an sie übergeben wird - und zwei neue Druckfunktionen mit verschiedenen Schnittstellen erstellt, die auch das gesamte an sie übergebene Array drucken. Ich nehme an, das Array ist quadratisch; eine rechteckige (nicht quadratische) Matrix leicht gehandhabt werden kann, insbesondere durch eine Variante auf pr1() wie pr2(int n, int m, int a[n][m]) - die fast identisch mit pr1() ist aber benötigen eine einzige Einstellung intern j gegen m anstelle von n zu testen.

#include <stdio.h> 

static void pr0(int a[][5]); 
static void pr1(int n, int a[n][n]); 

static void pr(int **a) 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     for (int j = 0; j < 5; j++) 
      printf("%3d", a[i][j]); 
     putchar('\n'); 
    } 
    putchar('\n'); 
} 

int main(void) 
{ 
    int a0[5][5] = 
    { 
     { 1, 4, 7, 11, 15 }, 
     { 2, 5, 8, 12, 19 }, 
     { 3, 6, 9, 16, 22 }, 
     { 10, 13, 14, 17, 24 }, 
     { 18, 21, 23, 26, 30 }, 
    }; 
    int *a[] = 
    { 
     (int[]){ 1, 4, 7, 11, 15 }, 
     (int[]){ 2, 5, 8, 12, 19 }, 
     (int[]){ 3, 6, 9, 16, 22 }, 
     (int[]){ 10, 13, 14, 17, 24 }, 
     (int[]){ 18, 21, 23, 26, 30 }, 
    }; 

    pr(a); 
    pr0(a0); 
    pr1(5, a0); 

    return 0; 
} 

static void pr0(int a[][5]) 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     for (int j = 0; j < 5; j++) 
      printf("%3d", a[i][j]); 
     putchar('\n'); 
    } 
    putchar('\n'); 
} 

static void pr1(int n, int a[n][n]) 
{ 
    for (int i = 0; i < n; i++) 
    { 
     for (int j = 0; j < n; j++) 
      printf("%3d", a[i][j]); 
     putchar('\n'); 
    } 
    putchar('\n'); 
} 

Die Probe Ausgang ist wunderbar einheitlich:

1 4 7 11 15 
    2 5 8 12 19 
    3 6 9 16 22 
10 13 14 17 24 
18 21 23 26 30 

    1 4 7 11 15 
    2 5 8 12 19 
    3 6 9 16 22 
10 13 14 17 24 
18 21 23 26 30 

    1 4 7 11 15 
    2 5 8 12 19 
    3 6 9 16 22 
10 13 14 17 24 
18 21 23 26 30 

Die drei Blöcke gleich sind.Gegeben eine Wahl, würde ich die Technik in pr1() verwenden, die VLAs (Arrays mit variabler Länge) in der Schnittstelle verwendet. Wenn Sie mit dem Argument int ** bleiben müssen, müssen Sie mit dem Array a, oder etwas ganz ähnliches bleiben. Es gibt sicherlich andere Möglichkeiten, das zu schaffen. Zum Beispiel:

int *a[] = { a0[0], a0[1], a0[2], a0[3], a0[4] }; 
4

Arrays und Zeiger können nicht austauschbar in alle möglich Anwendungsfällen verwendet werden, und Sie nur in einem von ihnen stolpern passieren. Manchmal kann ein int Array implizit in einen Zeiger konvertiert werden, und manchmal sollte es auch nicht sein.

In Ihrem Fall implizit (oder explizit) ein zu einem (int **) Umwandlung würde nicht funktionieren, einfach weil a Punkte auf das erste Element in Ihrem 2D-Array, wenn es als Zeiger betrachtet. Die Umwandlung von a in int ** würde pr die Information auf a verlieren, die ein Array ist. Folglich würde es als ein typisches (int **) in und versuchen, es zweimal zu dereferenzieren würde dazu führen, dass das erste Element in a() als eine Adresse behandelt werden und der Wert in dieser Adresse würde nachgeschlagen werden, was ich glaube nicht das gewünschte Verhalten von pr().

Idealerweise sollten Sie pr so deklarieren, dass ein 2D-Array als Parameter verwendet wird, nicht ein int **. Eine Erklärung von pr mit der erwähnten Reparatur ist unten angegeben.

void pr(int a[][5]){ 
    printf("%d", a[0][0]); 
} 

Nun erwähnen Sie in den Kommentaren zu Ihrer Frage, dass die Definition von pr kann nicht geändert werden. Um pr() nicht zu ändern, müssten Sie die Datenstruktur, die Sie in main haben, zu einer ähnlichen wie der folgenden ändern.

int main(){ 
    int a0[5]={1,4,7,11,15}; 
    int a1[5]={2,5,8,12,19}; 
    int a2[5]={3,6,9,16,22}; 
    int a3[5]={10,13,14,17,24}; 
    int a4[5]={18,21,23,26,30}; 
    int *a[5] = {a0, a1, a2, a3, a4}; 
    pr(a); 
} 

Beachten Sie, dass das obige Beispiel nicht die syntaktisch prägnanteste Möglichkeit ist, Ihr Ziel zu erreichen. Überprüfen Sie auch here, um diese Verwendung bei der Arbeit zu sehen.

Verwandte Themen