Réponses:
Non.
#define
est un jeton de préprocesseur: le compilateur lui-même ne le verra jamais.
typedef
est un jeton de compilateur: le préprocesseur ne s'en soucie pas.
Vous pouvez utiliser l'un ou l'autre pour obtenir le même effet, mais il est préférable d'utiliser celui qui convient à vos besoins
#define MY_TYPE int
typedef int My_Type;
Lorsque les choses deviennent "poilues", l'utilisation de l'outil approprié permet de corriger les choses
#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);
; la déclaration correcte est void fx_def(void (*fx)(int));
.
#define FX_TYPE(f) void (*f)(int)
. Vous déclareriez alors votre fonction comme:void fx_def(FX_TYPE(fx));
typedef
obéit aux règles de portée tout comme les variables, alors qu'il define
reste valide jusqu'à la fin de l'unité de compilation (ou jusqu'à une correspondance undef
).
En outre, certaines choses peuvent être faites avec typedef
qui ne peuvent être faites avec define
.
Par exemple:
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
Non, ils ne sont pas les mêmes. Par exemple:
#define INTPTR int*
...
INTPTR a, b;
Après le prétraitement, cette ligne se développe en
int* a, b;
J'espère que vous voyez le problème; a
aura seulement le type int *
; b
sera déclaré un plain int
(car le *
est associé au déclarateur, pas au spécificateur de type).
Comparez cela avec
typedef int *INTPTR;
...
INTPTR a, b;
Dans ce cas, les deux a
et b
auront le type int *
.
Il existe des classes entières de typedefs qui ne peuvent pas être émulées avec une macro de préprocesseur, comme des pointeurs vers des fonctions ou des tableaux:
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
Essayez de faire cela avec une macro de préprocesseur.
#define définit les macros.
typedef définit les types.
Maintenant en disant cela, voici quelques différences:
Avec #define, vous pouvez définir des constantes qui peuvent être utilisées au moment de la compilation. Les constantes peuvent être utilisées avec #ifdef pour vérifier comment le code est compilé et spécialiser certains codes en fonction des paramètres de compilation.
Vous pouvez également utiliser #define pour déclarer des fonctions de macro de recherche et de remplacement miniatures .
typedef peut être utilisé pour donner des alias aux types (ce que vous pourriez probablement faire avec #define également), mais c'est plus sûr en raison de la nature de recherche et de remplacement des constantes #define .
En plus de cela, vous pouvez utiliser la déclaration forward avec typedef qui vous permet de déclarer un type qui sera utilisé, mais qui n'est pas encore lié au fichier dans lequel vous écrivez.
Les macros de préprocesseur (" #define
's") sont un outil de remplacement lexical à la "recherche et remplacement". Ils sont totalement indépendants du langage de programmation et ne comprennent pas ce que vous essayez de faire. Vous pouvez les considérer comme un mécanisme de copier / coller glorifié - c'est parfois utile, mais vous devez l'utiliser avec précaution.
Les typedefs sont une fonctionnalité du langage C qui vous permet de créer des alias pour les types. Ceci est extrêmement utile pour rendre les types composés complexes (comme les structures et les pointeurs de fonction) lisibles et manipulables (en C ++, il existe même des situations où vous devez taper un type).
Pour (3): vous devriez toujours préférer les fonctionnalités de langage aux macros de préprocesseur lorsque cela est possible! Utilisez donc toujours des typedefs pour les types et des valeurs constantes pour les constantes. De cette façon, le compilateur peut réellement interagir avec vous de manière significative. N'oubliez pas que le compilateur est votre ami, vous devez donc lui en dire autant que possible. Les macros de préprocesseur font exactement le contraire en cachant votre sémantique au compilateur.
Ils sont très différents, bien qu'ils soient souvent utilisés pour implémenter des types de données personnalisés (c'est ce que je suppose que cette question porte).
Comme pmg l'a mentionné, il #define
est géré par le pré-processeur (comme une opération de copier-coller) avant que le compilateur ne voie le code, et typedef
est interprété par le compilateur.
L'une des principales différences (du moins en ce qui concerne la définition des types de données) est qu'elle typedef
permet une vérification de type plus spécifique. Par exemple,
#define defType int
typedef int tdType
defType x;
tdType y;
Ici, le compilateur voit la variable x comme un int, mais la variable y comme un type de données appelé «tdType» qui se trouve être de la même taille qu'un int. Si vous avez écrit une fonction qui a pris un paramètre de type defType, l'appelant pourrait passer un int normal et le compilateur ne connaîtrait pas la différence. Si la fonction prend à la place un paramètre de type tdType, le compilateur s'assurera qu'une variable du type approprié a été utilisée lors des appels de fonction.
En outre, certains débogueurs ont la capacité de gérer typedef
s, ce qui peut être beaucoup plus utile que d'avoir tous les types personnalisés répertoriés comme leurs types primitifs sous-jacents (comme ce serait le cas si #define
c'était utilisé à la place).
Non.
Typedef est un mot-clé C qui crée un alias pour un type.
#define est une instruction pré-processeur, qui crée un événement de remplacement de texte avant la compilation. Lorsque le compilateur accède au code, le mot «#defined» d'origine n'est plus là. #define est principalement utilisé pour les macros et les constantes globales.
AFAIK, non.
typedef
vous aide à configurer un «alias» pour un type de données existant. Pour par exemple. typedef char chr
;
#define
est une directive de préprocesseur utilisée pour définir des macros ou des substitutions générales de modèles. Pour par exemple. #define MAX 100
, remplace toutes les occurrences de MAX
par 100
Comme mentionné ci-dessus, il existe une différence clé entre #define
et typedef. La bonne façon de penser à cela est de voir un typedef comme étant un type "encapsulé" complet. Cela signifie que vous ne pouvez pas y ajouter après l'avoir déclaré.
Vous pouvez étendre un nom de type de macro avec d'autres spécificateurs de type, mais pas un nom de type typedef:
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
De plus, un nom typedef'd fournit le type de chaque déclinateur dans une déclaration.
#define fruit int *
fruit apple, banana;
Après le développement de la macro, la deuxième ligne devient:
int *apple, banana;
Apple est un pointeur vers un int, tandis que banana est un int. En comparaison. un typedef comme celui-ci:
typedef char *fruit;
fruit apple, banana;
déclare que la pomme et la banane sont identiques. Le nom au recto est différent, mais ce sont tous les deux des pointeurs vers un caractère.
Comme tout le monde l'a dit ci-dessus, ils ne sont pas les mêmes. La plupart des réponses indiquent typedef
être plus avantageux que #define
. Mais permettez-moi de mettre un point positif de #define
:
lorsque votre code est extrêmement gros, dispersé dans de nombreux fichiers, il est préférable de l'utiliser #define
; cela aide à la lisibilité - vous pouvez simplement prétraiter tout le code pour voir la définition de type réelle d'une variable à l'endroit de sa déclaration elle-même.
stdfx
, les objets valides de ce type sont des pointeurs vers des fonctions qui reçoivent un int et ne renvoient pas de valeur.