10
votes

Typedef est-il juste un remplacement de chaîne en code ou quelque chose d'autre?

J'étais curieux de savoir comment fonctionne exactement Typef.

typedef struct example identifier;

identifier x;


1 commentaires

8 Réponses :


0
votes

TypeDEF est un raccourci qui crée un nouveau nom pour (généralement complexe). Son objectif est plus étroit que le remplacement des chaînes du préprocesseur. Ainsi, il est moins sujet aux erreurs que les définitions de préprocesseur (qui sont analysées de manière récursive).


0 commentaires

0
votes

avec typlef vous faites un alias. Le compilateur remplace l'alias avec le code correct.

Si vous écrivez: P>

int mycompany = 100;


3 commentaires

Ce n'est pas un remplacement de chaîne et n'a rien à voir avec le préprocesseur. Le compilateur obtient société_id .


Je n'avais pas dit que c'est une directive de préprocesseur comme #define. J'ai dit que c'est pour faire un alias d'un type.


Je pense que le problème est avec la ligne 'Le compilateur obtient'. Le compilateur obtient le vrai code exactement comme vous l'avez écrit. Il interprète comme si le type d'origine était utilisé là-bas, cependant, de légères différences.



9
votes

A Typedef code> introduit un synonyme em> pour les types. Ce n'est pas un remplacement de chaîne simple, comme indiqué ci-dessous:

typedef int* int_ptr;
const int* a;    // pointer to const int
const int_ptr b; // const pointer to int


0 commentaires

34
votes

Non, ce n'est pas un remplacement de chaîne - ce serait des macros. Il crée un alias pour le type.

Typefefs sont préférés sur les macros pour des types personnalisés , en partie parce qu'ils peuvent coder correctement les types de pointeur. P>

typedef char *String_t;
#define String_d char *
String_t s1, s2;
String_d s3, s4;


4 commentaires

+1 pour la réponse et surtout le bon exemple sur la manière dont un remplacement de chaîne conduirait à un autre comportement


Eh bien, je viens de la copier de C-FAQ :)


Merci@amar pour une explication soignée :)


Il existe d'autres problèmes avec la manière dont les différents identificateurs sont gérés par le compilateur. En particulier, les noms Typef-ed et les types définis par l'utilisateur sont conservés dans différents espaces d'identifiant. J'ai ajouté que comme une réponse ci-dessous.



0
votes

Les macros sont effectuées par le préprocesseur et sont purement basées sur la substitution de texte. Ainsi, vous pourriez dire qu'ils sont assez stupides. Le préprocesseur acceptera à peu près toutes les ordures sans vérification de la syntaxe.

TypeDefs sont effectués par le compilateur lui-même et ils manipulent la table de type de compilateur en ajoutant un type dérivé que vous définissez. Ceci est soumis à une vérification complète de la syntaxe et un mécanisme spécifiquement pour les types uniquement.

Vous pouvez penser au compilateur à faire un "travail" similaire à quand vous déclarez un struct . Il y a une définition là-bas et le compilateur le transforme dans un type dans sa liste de types.


0 commentaires

5
votes

Tout d'accord en ce sens qu'il ne s'agit pas de substitution de type, et qu'il est bien meilleur que lorsque les pointeurs entrent dans le mélange, mais il existe également d'autres subtilités. En particulier, l'utilisation de TYPEDEF peut affecter la manière dont le code est analysé et la validité des programmes.

Les identificateurs définis par l'utilisateur C ++ sont conservés dans différents espaces de noms (pas dans le sens de la C ++, mais une sorte d'espace d'identification. ). Lorsque vous utilisez le mot-clé TYPEDEF, vous établissez un alias pour le type dans l'espace de nom global em>, où réside les fonctions. P> xxx pré>

une légère différence ici est qu'en C ++, le compilateur examinera d'abord dans l'espace Nom global em> et si non trouvé là-bas, il examinera également dans l'espace Nom de types: P>

// C
struct test {};
//void f( test t );      // error, test is not defined in the global namespace
void f( struct test t ); // ok, we are telling the compiler where to look

// C++
struct test {};
void f( test t );        // ok, no test defined in the global name space, 
                         // the compiler looks in the types name space
void g( struct test t ); // also ok, even if 'struct' not needed here.


0 commentaires

2
votes

Une distinction importante est que Typedef s a étendue .

Ce qui suit est un idiome commun xxx

Vous auriez souvent la définition du constructeur dans un fichier .CPP, avec la déclaration dans l'en-tête. Si vous utilisez foo (int x): bar (x) , vous oublierez de mettre à jour le constructeur si vous modifiez la hiérarchie de classe telle que foo-> wibble-> bar au lieu de foo -> bar. Personnellement, je vous recommande d'ajouter le "hérité" typlef à chaque sous-classe.

voir ici pour plus de détails: Utiliser" Super "en C ++


2 commentaires

@strager: attendez que vous devez hériter de quelque_template :: Type, / * Plus? * /> .


@Georg Fritzsche, Ah, j'ai vu (et écrit) que oui. Votre exemple le fait ressembler à ce que cela soit fait pour tous les cas, cependant (en particulier le commentaire de la barre "préféré à" "" ".



0
votes

Je trouve que TypeEfs facilite la lecture des signatures de fonction. Supposons que vous souhaitiez retourner un pointeur sur une matrice bidimensionnelle. Voici la manière lisible: xxx

et voici comment vous pouvez le faire sans typef: xxx

Notez que cette signature fait ne regarde pas tout comme la première version avec un "remplacement de chaîne" appliqué.

Si la syntaxe du déclarateur C n'était pas si laide (Stroustrup: "Je considère la syntaxe de la déclaration C une expérience qui a échoué"), TapeFefs n'aurait probablement pas été utilisé autant qu'ils sont maintenant.


0 commentaires