Antworten:
Nein.
#define
ist ein Präprozessor-Token: Der Compiler selbst wird es nie sehen.
typedef
ist ein Compiler-Token: Der Präprozessor kümmert sich nicht darum.
Sie können den einen oder anderen verwenden, um den gleichen Effekt zu erzielen, aber es ist besser, den richtigen für Ihre Bedürfnisse zu verwenden
#define MY_TYPE int
typedef int My_Type;
Wenn die Dinge "haarig" werden, macht es die Verwendung des richtigen Werkzeugs richtig
#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);
void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */
void fx_def(void (*)(int) fx);
; Die richtige Erklärung lautet void fx_def(void (*fx)(int));
.
#define FX_TYPE(f) void (*f)(int)
. Sie würden dann Ihre Funktion deklarieren als:void fx_def(FX_TYPE(fx));
typedef
Befolgen Sie die define
Gültigkeitsregeln genau wie Variablen, während sie bis zum Ende der Kompilierungseinheit (oder bis zu einem Abgleich undef
) gültig bleiben .
Es können auch einige Dinge erledigt werden, mit typedef
denen nicht gearbeitet werden kann define
.
Beispielsweise:
typedef int* int_p1;
int_p1 a, b, c; // a, b, c are all int pointers
#define int_p2 int*
int_p2 a, b, c; // only the first is a pointer, because int_p2
// is replaced with int*, producing: int* a, b, c
// which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c; // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp; // func_p is a pointer to a function that
// takes an int and returns an int
Nein, sie sind nicht gleich. Beispielsweise:
#define INTPTR int*
...
INTPTR a, b;
Nach der Vorverarbeitung wird diese Zeile auf erweitert
int* a, b;
Hoffentlich sehen Sie das Problem; nur a
wird den Typ haben int *
; b
wird als normal deklariert int
(da das *
dem Deklarator zugeordnet ist, nicht dem Typbezeichner).
Vergleichen Sie das mit
typedef int *INTPTR;
...
INTPTR a, b;
In diesem Fall haben beide a
und b
Typ int *
.
Es gibt ganze Klassen von Typedefs, die mit einem Präprozessor-Makro nicht emuliert werden können, z. B. Zeiger auf Funktionen oder Arrays:
typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20];
...
CALLBACK aCallbackFunc; // aCallbackFunc is a pointer to a function
// returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
// returning a pointer to a 20-element array
// of pointers to int
Versuchen Sie dies mit einem Präprozessor-Makro.
#define definiert Makros.
typedef definiert Typen.
Nun sagen wir das, hier sind ein paar Unterschiede:
Mit #define können Sie Konstanten definieren, die in der Kompilierungszeit verwendet werden können. Die Konstanten können mit #ifdef verwendet werden , um zu überprüfen, wie der Code kompiliert wird, und um bestimmten Code gemäß den Kompilierungsparametern zu spezialisieren.
Sie können auch verwenden #define Miniatur Suchen und ersetzen zu erklären Makro - Funktionen .
typedef kann verwendet werden , Aliase Typen zu geben (die Sie wahrscheinlich mit tun könnten #define auch), aber es ist sicherer , weil die Fund-und-Ersetzen - Natur von #define Konstanten.
Außerdem können Sie die Vorwärtsdeklaration mit typedef verwenden , mit der Sie einen Typ deklarieren können, der verwendet wird, aber noch nicht mit der Datei verknüpft ist, in die Sie schreiben.
Präprozessor-Makros (" #define
's") sind ein lexikalisches Ersatzwerkzeug a la "Suchen und Ersetzen". Sie sind völlig unabhängig von der Programmiersprache und haben kein Verständnis dafür, was Sie versuchen zu tun. Sie können sich diese als verherrlichte Kopier- / Einfügemechanik vorstellen - gelegentlich ist das nützlich, aber Sie sollten sie mit Vorsicht verwenden.
Typedefs sind eine C-Sprachfunktion, mit der Sie Aliase für Typen erstellen können. Dies ist äußerst nützlich, um komplizierte zusammengesetzte Typen (wie Strukturen und Funktionszeiger) lesbar und handhabbar zu machen (in C ++ gibt es sogar Situationen, in denen Sie einen Typ eingeben müssen ).
Für (3): Sie sollten immer Sprachfunktionen Präprozessormakros vorziehen, wenn dies möglich ist! Verwenden Sie daher immer typedefs für Typen und konstante Werte für Konstanten. Auf diese Weise kann der Compiler tatsächlich sinnvoll mit Ihnen interagieren. Denken Sie daran, dass der Compiler Ihr Freund ist, also sollten Sie ihm so viel wie möglich erzählen. Präprozessor-Makros machen genau das Gegenteil, indem sie Ihre Semantik vor dem Compiler verbergen .
Sie sind sehr unterschiedlich, obwohl sie häufig zur Implementierung benutzerdefinierter Datentypen verwendet werden (worum es bei dieser Frage vermutlich geht).
Wie bereits erwähnt, #define
wird pmg vom Vorprozessor (wie beim Ausschneiden und Einfügen) behandelt, bevor der Compiler den Code sieht, und typedef
vom Compiler interpretiert.
Einer der Hauptunterschiede (zumindest bei der Definition von Datentypen) besteht darin, dass typedef
eine spezifischere Typprüfung möglich ist. Beispielsweise,
#define defType int
typedef int tdType
defType x;
tdType y;
Hier sieht der Compiler die Variable x als int, aber die Variable y als Datentyp namens 'tdType', der zufällig dieselbe Größe wie ein int hat. Wenn Sie eine Funktion geschrieben haben, die einen Parameter vom Typ defType verwendet, könnte der Aufrufer ein normales int übergeben, und der Compiler würde den Unterschied nicht kennen. Wenn die Funktion stattdessen einen Parameter vom Typ tdType verwenden würde, würde der Compiler sicherstellen, dass bei Funktionsaufrufen eine Variable des richtigen Typs verwendet wird.
Einige Debugger können auch mit typedef
s umgehen , was viel nützlicher sein kann, als alle benutzerdefinierten Typen als zugrunde liegende primitive Typen aufzulisten (wie es der Fall wäre, wenn #define
sie stattdessen verwendet würden).
No.
typedef ist ein C Schlüsselwort , das einen Alias für einen Typ erzeugt.
#define ist eine Vorprozessoranweisung, die vor dem Kompilieren ein Textersetzungsereignis erstellt. Wenn der Compiler zum Code gelangt, ist das ursprüngliche Wort "#defined" nicht mehr vorhanden. #define wird hauptsächlich für Makros und globale Konstanten verwendet.
AFAIK, Nr.
typedef
hilft Ihnen beim Einrichten eines "Alias" für einen vorhandenen Datentyp. Zum Beispiel. typedef char chr
;;
#define
ist eine Präprozessor- Direktive, die zum Definieren von Makros oder allgemeinen Mustersubstitutionen verwendet wird. Zum Beispiel. #define MAX 100
, ersetzt alle Vorkommen von MAX
mit 100
Wie oben erwähnt, gibt es einen wesentlichen Unterschied zwischen #define
und typedef. Der richtige Weg, darüber nachzudenken, besteht darin, ein typedef als einen vollständigen "gekapselten" Typ anzusehen. Dies bedeutet, dass Sie es nicht hinzufügen können, nachdem Sie es deklariert haben.
Sie können einen Makrotypnamen mit anderen Typspezifizierern erweitern, jedoch nicht mit einem typedefd Typnamen:
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
Außerdem gibt ein typedef'd-Name den Typ für jeden Deklarator in einer Deklaration an.
#define fruit int *
fruit apple, banana;
Nach der Makroerweiterung wird die zweite Zeile:
int *apple, banana;
Apple ist ein Zeiger auf ein Int, während Banane ein Int ist. Im Vergleich. ein typedef wie folgt:
typedef char *fruit;
fruit apple, banana;
erklärt, dass sowohl Apfel als auch Banane gleich sind. Der Name auf der Vorderseite ist unterschiedlich, aber beide sind Zeiger auf ein Zeichen.
Wie alle oben sagten, sind sie nicht gleich. Die meisten Antworten typedef
sind vorteilhafter als #define
. Aber lassen Sie mich einen Pluspunkt setzen #define
:
Wenn Ihr Code extrem groß ist und über viele Dateien verteilt ist, ist es besser, ihn zu verwenden #define
. Es hilft bei der Lesbarkeit - Sie können einfach den gesamten Code vorverarbeiten, um die tatsächliche Typdefinition einer Variablen an der Stelle ihrer Deklaration selbst anzuzeigen.
stdfx
sind gültige Objekte dieses Typs Zeiger auf Funktionen, die ein int empfangen und keinen Wert zurückgeben.