Erwägen:
#define MAXROW 20
#define MAXCOL 60
typedef State Grid[MAXROW+2] [MAXCOL+2]
typedef enum state {DEAD,ALIVE} State
Wie verwende ich typedef
und typedef enum
in C? Was macht dieser Teil des Codes?
typedef enum state {DEAD,ALIVE} State;
| | | | | |^ terminating semicolon, required!
| | | type specifier | | |
| | | | ^^^^^ declarator (simple name)
| | | |
| | ^^^^^^^^^^^^^^^^^^^^^^^
| |
^^^^^^^-- storage class specifier (in this case typedef)
Das Schlüsselwort typedef
ist ein Pseudo-Speicherklassenspezifizierer. Syntaktisch wird es an derselben Stelle verwendet, wo ein Speicherklassenspezifizierer wie extern
oder static
verwendet wird. Es hat nichts mit Lagerung zu tun. Das bedeutet, dass durch die Deklaration nicht die Existenz von named objects eingeführt wird, sondern es werden Namen eingeführt, die Typ-Aliase sind.
Nach der obigen Deklaration wird der State
-Bezeichner zum Alias für den Typ enum state {DEAD,ALIVE}
. Die Deklaration liefert auch diesen Typ selbst. Das ist jedoch nicht typedef
. Jede Deklaration, in der enum state {DEAD,ALIVE}
als Typangabe erscheint, führt diesen Typ in den Geltungsbereich ein:
enum state {DEAD, ALIVE} stateVariable;
Wenn enum state
bereits eingeführt wurde, muss die typedef
folgendermaßen geschrieben werden:
typedef enum state State;
andernfalls wird enum
neu definiert, was ein Fehler ist.
Wie andere Deklarationen (mit Ausnahme von Funktionsparameterdeklarationen) kann die Deklaration typedef
mehrere Deklaratoren enthalten, die durch ein Komma getrennt sind. Darüber hinaus können sie abgeleitete Deklaratoren sein, nicht nur einfache Namen:
typedef unsigned long ulong, *ulongptr;
| | | | | 1 | | 2 |
| | | | | | ^^^^^^^^^--- "pointer to" declarator
| | | | ^^^^^^------------- simple declarator
| | ^^^^^^^^^^^^^-------------------- specifier-qualifier list
^^^^^^^---------------------------------- storage class specifier
Diese typedef
führt zwei Typnamen ein, ulong
und ulongptr
, basierend auf dem unsigned long
-Typ, der in der Spezifizierer-Qualifikationsliste angegeben ist. ulong
ist nur ein Alias für diesen Typ. ulongptr
ist dank der unsigned long
-Syntax als Zeiger auf *
deklariert. Diese Syntax ist eine Art Typkonstruktionsoperator, der absichtlich den unären *
für in Ausdrücken verwendete Zeiger-Dereferenzierung nachahmt. Mit anderen Worten ist ulongptr
ein Alias für den Typ "Zeiger auf unsigned long
".
Alias bedeutet, dass ulongptr
kein eindeutiger Typ ist von unsigned long *
. Dies ist ein gültiger Code, der keine Diagnose erfordert:
unsigned long *p = 0;
ulongptr q = p;
Die Variablen q
und p
haben exakt denselben Typ.
Das Aliasing von typedef
ist nicht textuell. Wenn zum Beispiel user_id_t
ein typedef
-Name für den Typ int
ist, können wir dies nicht einfach tun:
unsigned user_id_t uid; // error! programmer hoped for "unsigned int uid".
Dies ist eine ungültige Typenbezeichnerliste, die unsigned
mit einem Typedef-Namen kombiniert. Dies kann mit dem C-Präprozessor durchgeführt werden:
#define user_id_t int
unsigned user_id_t uid;
dabei wird user_id_t
vor der Syntaxanalyse und -übersetzung auf das Token int
erweitert. Dies mag zwar als Vorteil erscheinen, ist aber falsch. vermeiden Sie dies in neuen Programmen.
Zu den Nachteilen, dass es für abgeleitete Typen nicht gut funktioniert:
#define silly_macro int *
silly_macro not, what, you, think;
Diese Deklaration deklariert what
, you
und think
nicht als Typ "Zeiger auf int", da die Makroerweiterung Folgendes ist:
int * not, what, you, think;
Der Typbezeichner ist int
und die Deklaratoren sind *not
, what
, you
und think
. not
hat also den erwarteten Zeigertyp, die restlichen Bezeichner jedoch nicht.
Und das ist wahrscheinlich 99% von allem über typedef
und Typ Aliasing in C.
typedef
definiert einen neuen Datentyp. So können Sie haben:
typedef char* my_string;
typedef struct{
int member1;
int member2;
} my_struct;
Sie können also jetzt Variablen mit diesen neuen Datentypen deklarieren
my_string s;
my_struct x;
s = "welcome";
x.member1 = 10;
Bei enum
sind die Dinge etwas anders - betrachten Sie die folgenden Beispiele:
enum Ranks {FIRST, SECOND};
int main()
{
int data = 20;
if (data == FIRST)
{
//do something
}
}
mit typedef enum
wird ein Alias für einen Typ erstellt:
typedef enum Ranks {FIRST, SECOND} Order;
int main()
{
Order data = (Order)20; // Must cast to defined type to prevent error
if (data == FIRST)
{
//do something
}
}
Nur eine Ergänzung:
6.7.8 Typdefinitionen
Eine Typedef-Deklaration führt keinen neuen Typ ein, sondern nur ein Synonym für den so angegebenen Typ.
open-std.org ISO/IEC 9899: 2017
Personen, die damit einverstanden sind, dass typedef
einen neuen Datentyp in C erstellt, werden in der Funktion free()
gesucht und setzen alle Verweise auf ihren Namen auf NULL
.