Was ist die Ursache des flexiblen Array-Mitglieds nicht am Ende des Strukturfehlers?

Lesezeit: 3 Minuten

Benutzeravatar von csta
csta

Ich frage mich, warum ich immer wieder bekomme error: flexible array member not at end of struct Fehler, wenn ich malloc anrufe. Ich habe eine Struktur mit einem Array variabler Länge, und ich erhalte immer wieder diesen Fehler.

Die Struktur ist,

typedef struct {
  size_t N;
  double data[];
  int label[];
} s_col; 

und der Aufruf an malloc lautet:

col = malloc(sizeof(s_col) + lc * (sizeof(double) + sizeof(int)));

Ist das der richtige Aufruf von malloc?

Benutzeravatar von Jerry Coffin
Jerry Sarg

Sie können nur ein flexibles Array-Mitglied in einer Struktur haben, und es muss immer das letzte Mitglied der Struktur sein. Mit anderen Worten, in diesem Fall haben Sie einen Fehler gemacht, bevor Sie anrufen mallocbis zu dem Punkt, dass es wirklich keine Möglichkeit gibt, anzurufen malloc richtig für diese Struktur.

Um zu tun, was Sie zu wollen scheinen (Arrays mit der gleichen Anzahl von data und label Mitglieder), könnten Sie Folgendes in Betracht ziehen:

struct my_pair { 
    double data;
    int label;
};

typedef struct { 
   size_t N;
   struct my_pair data_label[];
};

Beachten Sie jedoch, dass dies etwas anders ist: anstelle eines Arrays von doubles gefolgt von einem Array von ints, es gibt Ihnen ein Array von eins double gefolgt von einem intdann die nächste doublenächste int, usw. Ob dies dem Gleichen nahe genug kommt oder nicht, hängt davon ab, wie Sie die Daten verwenden (z. B. für die Übergabe an eine externe Funktion, die ein zusammenhängendes Array erwartet, müssen Sie die Dinge wahrscheinlich anders machen).

  • Seltsamerweise beantwortet diese positive Antwort die Frage nicht gut: „Was ist die Ursache …“ Sie gibt eine Regel an (ein flexibles Array-Mitglied kann nur das letzte sein), gibt aber keine Quelle für die Regel an (C 2011/ 2018 6.7.2.1 18) oder einen Grund (die Speicherorte späterer Member konnten nicht ermittelt werden, da dem Compiler das Since des flexiblen Arrays nicht bekannt ist).

    – Eric Postpischil

    7. September 2020 um 14:38 Uhr

  • @EricPostpischil: Jemand, der mit einer Strukturdeklaration mit zwei flexiblen Array-Mitgliedern beginnt, muss nur erkennen, dass dies nicht zulässig ist, kein Zitat des spezifischen Teils des Standards, der dies verbietet. Glauben Sie mir, ich habe den Standard zitiert eine Menge von Zeiten, in denen es Sinn machte (fühlen Sie sich frei, meine Beiträge durchzusehen, wenn Sie das nicht glauben). Aber ich bin mir ziemlich sicher, dass dies in diesem Fall nur ablenken, nicht informieren würde.

    – Jerry Sarg

    8. September 2020 um 3:18 Uhr


Bei einer Strukturdefinition und einem Zeiger auf den Beginn einer Struktur ist es erforderlich, dass der C-Compiler auf jedes Element der Struktur zugreifen kann, ohne auf etwas anderes zugreifen zu müssen. Da die Position jedes Elements innerhalb der Struktur durch die Anzahl und Typen der vorhergehenden Elemente bestimmt wird, erfordert der Zugriff auf ein beliebiges Element, dass die Anzahl und die Typen aller vorhergehenden Elemente bekannt sind. In dem besonderen Fall, in dem das letzte Element ein Array ist, stellt dies keine besondere Schwierigkeit dar, da für den Zugriff auf ein Element in einem Array bekannt sein muss, wo es beginnt (was die Kenntnis der Anzahl und des Typs von vorangehend Elemente, und nicht die Anzahl der Elemente im Array selbst) und den Elementindex (von dem der Compiler annehmen kann, dass er kleiner ist als die Anzahl der Elemente, für die Platz vorhanden ist, ohne etwas über die Arraygröße wissen zu müssen). Wenn ein flexibles Array-Member jedoch an einer anderen Stelle als am Ende einer Struktur auftaucht, hängt die Position aller folgenden Elemente von der Anzahl der Elemente im Array ab – etwas, das der Compiler nicht wissen wird.

typedef struct {
  size_t N;
  double data[];
  int label[];
} s_col; 

Sie können kein flexibles Arraymitglied haben (double data[]) mitten drin. Berücksichtigen Sie die fest codierte Arraygröße oder double *data

  • Ich verstehe nicht, mir wurde beigebracht, dass “T * var” dasselbe ist wie “T var”.[]”

    – Lukas1985

    21. März 2014 um 14:09 Uhr

  • @ lukasz1985: Was Sie sagen, ist im Zusammenhang mit einem Funktionsargument in gewisser Weise wahr, bei dem Sie “ein Array-Manipulationsargument” angeben können, das technisch durch einen Zeiger implementiert wird. Normalerweise (dh hier) ist ein Array ein Array und ein Zeiger ein Zeiger.

    – stan423321

    12. April 2014 um 19:55 Uhr

1386980cookie-checkWas ist die Ursache des flexiblen Array-Mitglieds nicht am Ende des Strukturfehlers?

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

Privacy policy