Kann ein zweidimensionales Array in C ohne explizite Größe initialisiert werden?

Lesezeit: 5 Minuten

Ich habe eine Frage zu zweidimensionalen Arrays in C. Ich weiß jetzt (aus direkter Compiler-Erfahrung), dass ich ein solches Array nicht analog zu eindimensionalen Arrays wie diesem initialisieren kann:

int multi_array[][] = {
  {1,2,3,4,5},
  {10,20,30,40,50},
  {100,200,300,400,500}
};

> compiler output:

gcc -o arrays arrays.c
arrays.c: In function ‘main’:
arrays.c:8:9: error: array type has incomplete element type

Die nächste funktionierende Lösung besteht darin, die Anzahl der Spalten explizit wie folgt anzugeben:

int multi_array[][5] = {
  {1,2,3,4,5},
  {10,20,30,40,50},
  {100,200,300,400,500}
};

Meine Frage ist: Kann man das sauber machen? ohne die Nummer explizit angeben (die der Compiler schließlich selbst ableiten können sollte)? Ich spreche nicht davon, es manuell zu konstruieren malloc oder etwas, aber eher etwas in der Nähe von dem, was ich versucht habe. Kann jemand, der sich mit C-Compilern auskennt, aus einer Low-Level-Perspektive erklären, warum mein erster Versuch nicht funktioniert?

Ich habe schlicht verwendet gcc ohne nicht standardmäßige Optionen zum Kompilieren des Codes.

Vielen Dank

  • Wie werden Sie eine Funktion deklarieren, die verwendet multi_array als einer seiner Parameter?

    – Lee Duhem

    28. Februar 2014 um 16:27 Uhr

  • im ersten Fall kann der Compiler auf beide Dimensionen schließen multi_arrayaber in diesem Fall, wenn der Programmierer unterschiedliche Größen bereitstellt, wird ein Fehler wie “nicht übereinstimmende Arraygröße bei der Initialisierung” ausgegeben … Ich denke, der Designer hat es vorgezogen, dass der Programmierer angibt, welche Größe er erwartet, und dann mit dieser Größe überprüft.

    – ÄhmNyobe

    28. Februar 2014 um 16:35 Uhr


  • “Kann jemand, der sich mit C-Compilern auskennt, aus einer Low-Level-Perspektive erklären, warum mein erster Versuch nicht funktioniert?” – Weil die Spezifikation explizite Größen für alle Dimensionen nach einer verlangt. Jetzt, warum Das ist der Fall, ich kann nicht sagen, dass ich es weiß.

    – Ed S.

    28. Februar 2014 um 18:18 Uhr

  • @clcto: Es kann durch die Initialisierung abgeleitet werden. Das ist das Verwirrende, nicht die Tatsache, dass die Dimensionen allgemein definiert werden müssen.

    – Ed S.

    28. Februar 2014 um 23:24 Uhr

  • Als C entworfen wurde, waren Computer mit 16 KB RAM üblich – C wurde zumindest größtenteils auf einem mit 8 KB aufgebaut – also ist es leicht zu erkennen, warum es anfangs nicht in der Sprache war. Warum ist es jetzt nicht in der Sprache? Niemand hat sich jemals genug darum gekümmert, die Sprache zu ändern, wenn der Redakteur eines Programmierers Kommas für Sie zählen kann, würde ich vermuten.

    – jthill

    26. Mai 2014 um 17:26 Uhr

2D-Arrays ein C werden in zusammenhängenden Speicherorten gespeichert. Wenn Sie also weder die Anzahl der Zeilen noch die Anzahl der Spalten angeben, woher weiß dann der Compiler, wie viele Zeilen und Spalten es gibt?

Für ein Zeilenhauptmatrix, befinden sich Zeileninhalte an zusammenhängenden Speicherpositionen. Sie müssen also mindestens die Anzahl der Spalten angeben. In ähnlicher Weise müssen Sie für eine Spalten-Major-Matrix mindestens die Anzahl der Zeilen angeben. Ob es sich um Zeilenhaupt oder Spaltenhaupt handelt, wird durch die Architektur definiert. Es scheint, dass Sie eine Reihenhauptarchitektur haben.

  • Ja, aber im Fall des Fragestellers stellt er die Initialisierer bereit, und daraus könnte der Compiler auf die Größe der ersten Dimension schließen, die der Fragesteller in seiner Frage bemerkt hat.

    – Jabberwocky

    28. Februar 2014 um 16:29 Uhr

Sie können dies mit der zusammengesetzten Literalfunktion von C99 tun.

Eine Teilidee ist, dass die Länge einer Initialisierungsliste wie folgt bestimmt werden kann:

sizeof (int[]){ 1, 2, 3, 4, 5 } / sizeof(int)

Wir brauchen eine Problemumgehung für die Tatsache, dass die einzige Möglichkeit, ein Argument mit einem Komma an ein Makro zu übergeben, darin besteht, Klammern um (einen Teil) des Arguments zu setzen:

#define ROW(...) { __VA_ARGS__ }

Dann leitet das folgende Makro die zweite Dimension aus der ersten Zeile ab:

#define MAGIC_2DARRAY(type, ident, row1, ...) \
        type ident[][sizeof (type[])row1 / sizeof (type)] = { \
                row1, __VA_ARGS__ \
        }

Es funktioniert nur, wenn mindestens zwei Zeilen vorhanden sind.

Beispiel:

MAGIC_2DARRAY(int, arr, ROW(7, 8, 9), ROW(4, 5, 6));

Sie möchten dies wahrscheinlich nicht in einem echten Programm verwenden, aber es ist möglich.

Um diese Art von Array an Funktionen zu übergeben, ist die C99-Funktion für Arrays mit variabler Länge nützlich, mit einer Funktion wie:

void printarr(int rows, int columns, int array[rows][columns]) { ... }

aufgerufen als:

printarr(sizeof arr / sizeof arr[0], sizeof arr[0] / sizeof arr[0][0], arr);

Keine direkte Antwort auf diese Fragen im ursprünglichen Beitrag, ich möchte nur darauf hinweisen, dass das, was der Fragesteller vorschlägt, möglicherweise keine so gute oder nützliche Idee ist.


Der Compiler kann in der Tat daraus schließen

int multi_array[][] = {
  {1,2,3,4,5},
  {10,20,30,40,50},
  {100,200,300,400,500}
};

die Struktur von multi_array.

Aber wenn Sie eine Funktion deklarieren und definieren möchten (diese Deklaration und Definition könnte sich in einer anderen Kompilierungseinheit oder Quelldatei befinden), die akzeptiert werden soll multi_array Als eines seiner Argumente müssen Sie noch so etwas tun

int foo(..., int multi_array[][COL], ...) { }

Compiler braucht das COL richtige Zeigerarithmetik zu machen foo().

Normalerweise definieren wir COL als Makro, das durch eine Ganzzahl in einer Header-Datei ersetzt wird, und verwenden Sie es in den Definitionen von multi_array und foo():

int multi_array[][COL] = { ... };

int foo(..., int multi_array[][COL], ...) { }

Auf diese Weise ist es einfach sicherzustellen, dass sie gleich sind. Und lassen Sie den Compiler die Struktur von ableiten multi_array Wenn Sie ihm eine falsche Initialisierung geben, führen Sie gemäß seiner Initialisierung tatsächlich einen Fehler in Ihren Code ein.

Nein, das kannst du nicht. Wenn Sie nicht einmal initialisieren, können Sie kein int-Array definieren[][];

Erstellen Sie eine Struktur mit 1d-Arrays. Wenn Sie jedoch dieser Methode folgen, können Sie neue Arrays erstellen, es handelt sich jedoch um einen Funktionsaufruf zum Ändern von Größen und Werten. Ein dynamischer Matrixansatz könnte der Lösung Ihres Problems nahe kommen.

  • Es wird besser sein, das OP-Problem anzusprechen. Er hat in der Frage angegeben, dass er nichts über die dynamische Zuordnung hören möchte.

    – ÄhmNyobe

    28. Februar 2014 um 16:47 Uhr

  • Es wird besser sein, das OP-Problem anzusprechen. Er hat in der Frage angegeben, dass er nichts über die dynamische Zuordnung hören möchte.

    – ÄhmNyobe

    28. Februar 2014 um 16:47 Uhr

1432220cookie-checkKann ein zweidimensionales Array in C ohne explizite Größe initialisiert werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy