it-swarm.com.de

Wie verwende ich typedef und typedef enum in C?

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?

45
user39555
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.

90
Kaz

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
   }
}
22
Pandrei

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.

0