2017-09-05 8 views
20

Ich habe eine Struktur in .h definiertWie mache ich gcc warn undefinierte Struktur?

struct buf_stats { 
    // *** 
}; 

dann in C-Datei

struct buf_stats *bs = malloc(sizeof(struct buf_states*)) ; 

wo buf_states ein Tippfehler ist.

aber gcc warnt mich nicht, obwohl ich -Wall verwendet

und dieser Fehler/Tippfehler kostete mich 3 Stunden, um herauszufinden.

Wie mache ich gcc warn undefined struct so?

+0

Heh? Was war die Fehlermeldung, die du bekommen hast? –

+0

@SouravGhosh Ich denke, es gab keine Fehlermeldung und das ist, was OP fragt. – Yunnosch

+17

Willst du genug Platz für einen Zeiger? Der Compiler braucht nicht wirklich die Größe dessen, worauf er hinweist. Oder möchten Sie malloc für eine Struktur? In diesem Fall gibt es einen weiteren Tippfehler, das zweite '*'. – Yunnosch

Antwort

36

In Ihrem Code

struct buf_stats *bs = malloc(sizeof(struct buf_states*)) ; 

ist falsch aus vielen Gründen, wie

  • Sie einen undefinierten Typ (wie Sie bereits erwähnt)
  • Du Zuteilung Art und Weise weniger Speicher (Zuteilung für a Zeiger-zu-Typ anstelle der Typ)

Aber Sie Compiler nicht viel in _this_case für diese besondere Art des Fehlers helfen kann, als

  • ein Zeiger auf (jede) geben eine Plattform, die eine definierte Größe hat, für dass die Struktur (dh der Typ der Variablen, auf die er zeigt) muss nicht vollständig sein (definiert). Das ist der Grund, warum wir auf sich selbst verweisende Strukturen haben können, oder?

  • malloc() hat keine Ahnung von dem Zielvariablentyp. Es liest nur das Argument für die benötigte Größe, gibt einen Zeiger (vom Typ void *) an den zugewiesenen Speicher zurück und bei Zuweisung wird dieser zum Zieltyp geändert. Es kann nicht Mismatch in der Zielgröße (Typ) mit der zugewiesenen Speichergröße berechnen.

Am bequemsten und einfachsten Weg zu vermeiden diese Art von Fehler ist, nicht auf den hartcodierte Typen zu verwenden, um direkt als Operand sizeof vielmehr die variable Referenz verwenden.

So etwas wie

struct buf_stats *bs = malloc(sizeof *bs) ; // you can write that as (sizeof (*bs)) also 
              // sizeof *bs === sizeof (struct buf_stats) 

die

struct buf_stats *bs = malloc(sizeof(struct buf_stats)) ; 

zu

gleichwertig ist, aber robuster und weniger fehleranfällig.

Hinweise:

  1. Sie brauchen nicht die Klammern, wenn der Operand kein Typname ist.
  2. Diese Anweisung muss bei Änderung des Typs der Zielvariablen bs nicht geändert werden.
+2

Es ist wahrscheinlich erwähnenswert, dass das '*' in 'sizeof * bs' * nicht * einen Zeiger, sondern eine Dereferenz anzeigt. 'bs' ist ein Zeiger, also' * bs' ist der Strukturwert selbst, auf dem sizeof hier aufgerufen wird. – tomsmeding

+0

Außerdem ist Note 1 gut, weil sie tatsächlich einen Fehler erzeugt, der ähnlich dem von @Sato ist, wenn entweder 'struct but_stats' nicht vollständig ist oder' bs' ein Typname anstelle eines Variablennamens ist . – Leushenko

+1

Ich habe Plattformen gesehen, bei denen Zeiger auf unterschiedlich große Dinge unterschiedliche Größen hatten. (void * war der größte Zeiger auf einen beliebigen Datentyp, um dies zu ermöglichen.) – Joshua

17

Sie können nicht. Unter Verwendung eines Ausdrucks wie struct foo * (ein Zeiger auf einen Strukturtyp) deklariert diese Struktur als unvollständiger Typ. Eine Größe ist nicht bekannt, aber für die Größe des Zeigers ist es nicht notwendig.

Das heißt, sieht der Code falsch, wie Sie die Größe der Struktur (nicht die Größe des Zeigers) benötigen, so mit dem folgenden Code:

struct buf_stats *bs = malloc(sizeof(struct buf_states)); 

Sie eine bekommen würde Fehler.

Es gibt einen besseren Weg, einen solchen Code zu schreiben:

struct buf_stats *bs = malloc(sizeof *bs); 

Der Ausdruck *bs hat den richtigen Typ für sizeof, auch wenn Sie später die Art ändern.

Verwandte Themen