Typesafe enums in C?

7

Wenn ich mehr als ein enum habe, zB:

%Vor%

Wie kann ich die Verwendung der korrekten enum erzwingen? Zum Beispiel möchte ich nicht, dass jemand hello verwendet, wenn sie one für besseres Debugging und bessere Lesbarkeit verwenden sollten.

    
drum 11.02.2013, 22:45
quelle

6 Antworten

9

In C können Sie es mit dem Standardcode vortäuschen.

%Vor%

Dies sollte keinen Overhead verursachen und erzeugt Fehler anstelle von Warnungen:

%Vor%

Beachten Sie, dass ich keine GNU-Erweiterungen verwende und keine unechten Warnungen generiert werden. Nur Fehler. Beachte auch, dass ich eine Version von GCC verwende, die so alt ist wie Dreck,

%Vor%

Dies sollte mit jedem Compiler funktionieren, der die zusammengesetzten Literale von C99 unterstützt.

    
Dietrich Epp 11.02.2013, 23:09
quelle
8

Clang gibt die folgende Warnung aus, die das Beste ist, was Sie tun können (Obwohl der Benutzer die Warnung auf einen Fehler aktualisieren könnte).

%Vor%

Compiler-Ausgabe:

%Vor%

Wenn Benutzer Fehler und Warnungen vom Compiler ignorieren, können Sie nicht viel tun, um ihnen zu helfen.

    
Bill Lynch 11.02.2013 22:48
quelle
2

Dies ist die Antwort, die Sie nicht hören möchten. In C kannst du nicht wirklich. Nun, wenn Ihr C-Code in der "Clean C" -Untergruppe von C ++ wäre, könnten Sie mit dem C ++ - Compiler kompilieren, um alle Fehler zu bekommen, die falschen enum / int-Werte zu verwenden, usw.

    
ldav1s 11.02.2013 22:59
quelle
2

Leider enum sind ein Schwachpunkt im Typsystem von C. Variablen eines enum -Typs sind vom Typ enum , aber die Konstanten, die Sie mit enum deklarieren, haben den Typ int .

Also in Ihrem Beispiel

%Vor%

hello und one sind zwei Namen für denselben Wert, nämlich 0 und mit demselben Typ int .

holla und eins haben wieder den Wert 0 , haben aber ihre jeweiligen Typen.

Wenn Sie eine "offizielle" Typsicherheit für "echte" Konstanten erzwingen wollen, also Entitäten, die den gewünschten Typ und Wert haben, müssten Sie einige komplexere Konstrukte verwenden:

%Vor%

Die Zuweisung im Makro GREETING stellt sicher, dass das Ergebnis ein "rvalue" ist, so dass es nicht geändert werden kann und vom Compiler nur für seinen Typ und Wert genommen wird.

    
Jens Gustedt 11.02.2013 23:09
quelle
1

Wenn Sie auch den gültigen Bereich sicherstellen möchten, gibt es eine Technik, die mit dem kleinen Overhead einer Zeiger-Dereferenzierung zum Erhalten des ganzzahligen Werts - und einer großen Anzahl von Textbausteinen - einhergeht. Es kann immer noch nützlich sein, weil es Ihnen hilft, Bereichsüberprüfungscode zu schreiben, wo es sonst notwendig wäre.

Grüße.h:

%Vor%

Grüße.c:

%Vor%

Beispiel main.c:

%Vor%

Ja, eine Menge zu tippen, aber Sie erhalten volle Art und Reichweite Sicherheit. Keine andere Kompilierungseinheit kann jemals eine struct greetings instanziieren, so dass Sie vollkommen sicher sind.

Bearbeiten 2015-07-04: Zum Schutz vor NULL gibt es zwei Möglichkeiten. Verwenden Sie entweder NULL als Standardwert ( #define Greetings_hello 0 anstelle des aktuell verwendeten Zeigers). Dies ist sehr praktisch, aber gibt die Sicherheit für Standardaufzählungswerte zurück, NULL kann für jede Aufzählung verwendet werden. Oder deklariere es ungültig und überprüfe es entweder in den Accessor-Methoden, gebe einen Fehler zurück oder verwende etwas wie GCCs __attribute__((nonnull())) , um es zur Kompilierzeit abzufangen, zB in greetings.h:

%Vor%     
Felix Palmen 01.07.2015 15:20
quelle
-2

Sie können typedef Ihre enums definieren und dann Variablen und Funktionsargumente dieser Typen deklarieren.

    
oleg_g 11.02.2013 22:48
quelle

Tags und Links