Question

J'ai regardé par un code et a remarqué que la convention était de transformer les types de pointeur comme

SomeStruct* 

dans

typedef SomeStruct* pSomeStruct;

Y at-il le mérite à cela?

Était-ce utile?

La solution

Cela peut être approprié lorsque le pointeur lui-même peut être considérée comme une « boîte noire », à savoir, un élément de données dont la représentation interne doit être sans rapport avec le code.

Pour l'essentiel, si votre code jamais déréférencer le pointeur, et vous passez juste autour des fonctions API (parfois par référence), non seulement le typedef réduire le nombre de *s dans votre code, mais suggère aussi le programmeur que le pointeur ne doit pas vraiment être avec immiscé.

Cela rend également plus facile de changer l'API à l'avenir si le besoin se fait sentir. Par exemple, si vous passez à l'aide d'un ID plutôt qu'un pointeur (ou vice versa) le code existant ne cassera pas parce que le pointeur n'a jamais été censé être déréférencé en premier lieu.

Autres conseils

Pas dans mon expérience. Cacher la « * » rend difficile à lire le code.

La seule fois que j'utilise un pointeur à l'intérieur du typedef est en matière de pointeurs de fonctions:

typedef void (*SigCatcher(int, void (*)(int)))(int);

typedef void (*SigCatcher)(int);

SigCatcher old = signal(SIGINT, SIG_IGN);

Dans le cas contraire, je les trouve plus déroutantes qu'utiles.


La déclaration frappée-out est le type correct pour un pointeur vers la fonction signal(), non du receveur de signal. Il pourrait être plus clair (en utilisant le type de SigCatcher corrigé ci-dessus) par écrit:

 typedef SigCatcher (*SignalFunction)(int, SigCatcher);

Ou, pour déclarer la fonction signal():

 extern SigCatcher signal(int, SigCatcher);

Autrement dit, un SignalFunction est un pointeur vers une fonction qui prend deux arguments (un int et un SigCatcher) et renvoie un SigCatcher. Et signal() lui-même est une fonction qui prend deux arguments (un int et un SigCatcher) et retourne un SigCatcher.

Cela peut vous aider à éviter certaines erreurs. Par exemple, dans le code suivant:

int* pointer1, pointer2;

pointer2 n'est pas un int * , il est simple int . Mais avec typedefs ce ne va pas se produire:

typedef int* pInt;
pInt pointer1, pointer2;

Ils sont à la fois int * maintenant.

Ma réponse est un "non".

Pourquoi?

Eh bien, tout d'abord, vous échangez simplement un caractère unique * pour un autre p de caractère. C'est zéro gain. Cela seul devrait vous empêcher de faire cela comme il est toujours mauvais de faire des choses supplémentaires qui est inutile.

En second lieu, et qui est la raison importante, * qui est porteur de sens pas bon pour cacher . Si je passe quelque chose à une fonction comme ceci

void foo(SomeType bar);

void baz() {
    SomeType myBar = getSomeType();
    foo(myBar);
}

Je ne pense pas le sens de myBar à changer en passant à foo(). Après tout, je passe par la valeur, de sorte foo() ne voit jamais une copie de droit myBar? Pas quand SomeType est aliasé pour signifier une sorte de pointeur!

Cela vaut pour les pointeurs C et C ++ pointeurs intelligents: Si vous masquez le fait qu'ils sont des pointeurs vers vos utilisateurs, vous allez créer une confusion qui est tout à fait inutile. Alors, s'il vous plaît, ne pas vos pointeurs un alias.

(je crois que l'habitude de typedefing types de pointeur est juste une tentative malavisée de cacher combien d'étoiles on a en tant que programmeur http://wiki.c2.com/?ThreeStarProgrammer .)

Ceci est une question de style. Vous voyez ce genre de code très fréquemment dans les fichiers d'en-tête Windows. Bien qu'ils ont tendance à préférer la version de tous cas supérieure au lieu de préfixer avec un p minuscule.

Personnellement, j'éviter cette utilisation de typedef. Il est beaucoup plus clair que l'utilisateur disent explicitement qu'ils veulent un Foo * que PFoo. années TypeDef sont mieux adaptés ces jours-ci pour faire STL lisible:)

typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;

(comme autant de réponses) dépend.

En C Ceci est très fréquent que vous essayez de dissimuler qu'un objet est un pointeur. Vous essayez de laisser entendre que cela est l'objet que toutes vos fonctions manipulables (nous savons qu'il est un pointeur au-dessous, mais il représente l'objet que vous manipulez).

MYDB   db = MYDBcreateDB("Plop://djdjdjjdjd");

MYDBDoSomthingWithDB(db,5,6,7);
CallLocalFuc(db); // if db is not a pointer things could be complicated.
MYDBdestroyDB(db);

En dessous MYDB est probablement un pointeur à un objet.

En C ++ ce n'est plus nécessaire.
Principalement parce que nous pouvons passer les choses par référence et les méthodes sont incorporées dans la déclaration de classe.

MyDB   db("Plop://djdjdjjdjd");

db.DoSomthingWithDB(5,6,7);
CallLocalFuc(db);   // This time we can call be reference.
db.destroyDB();     // Or let the destructor handle it.

Typedef est utilisé pour rendre le code plus lisible, mais en faisant pointer comme typedef augmentera la confusion. Mieux vaut éviter les pointeurs typedef.

Discussion dressé en supposant la langue d'intérêt est C. Ramifications C ++ n'a pas été pris en considération.

Utilisation d'un typedef pointeur pour une structure sans étiquette

La question taille d'une struct qui est défini comme un pointeur soulève un côté lumière intéressante sur l'utilisation typedef pour (la structure ) pointeurs.

Tenez compte du type de structure en béton sans étiquette (non opaque) définition:

typedef struct { int field1; double field2; } *Information;

Les détails des membres sont complètement tangentiellement à cette discussion; tout ce qui compte est que ce pas un type opaque comme typedef struct tag *tag; (et vous ne pouvez pas définir ces types opaques via une typedef sans étiquette).

La question posée est «comment pouvez-vous trouver la taille de cette structure?

La réponse courte est « que par une variable de type ». Il n'y a pas d'étiquette à utiliser avec sizeof(struct tag). Vous ne pouvez pas écrire utilement sizeof(*Information) , par exemple, et sizeof(Information *) est la taille d'un pointeur vers le type de pointeur, pas la taille du type de structure.

vous ne pouvez pas En fait, si vous voulez allouer une telle structure, créer une exception via l'allocation dynamique (ou des techniques de substitution qui simulent l'allocation dynamique). Il n'y a pas moyen de créer une variable locale du type de structure dont les pointeurs sont appelés Information, ni est-il un moyen de créer un champ de fichier variable (globale ou static) du type de structure, ni est-il un moyen d'intégrer une telle structure (par opposition à un pointeur vers une telle structure) en un autre type de structure ou d'union.

Vous pouvez - devez - écrire:

Information info = malloc(sizeof(*info));

En dehors du fait que le pointeur est caché dans le typedef, c'est une bonne pratique - si le type de changements de info, l'allocation de taille demeure exacte. Mais dans ce cas, il est aussi la seule façon d'obtenir la taille de la structure et d'affecter la structure. Et il n'y a pas d'autre moyen de créer une instance de la structure.

Est-ce dangereux?

Cela dépend de vos objectifs.

Ce n'est pas un type opaque -. Les détails de la structure doivent être définies lorsque le type de pointeur est typedef'd

Il est un type qui ne peut être utilisé avec allocation dynamique de mémoire.

Il est un type qui est sans nom. Le pointeur sur le type de structure a un nom, mais le type de structure elle-même ne fonctionne pas.

Si vous souhaitez appliquer l'allocation dynamique, cela semble être une façon de le faire.

Dans l'ensemble, cependant, il est plus susceptible de causer de la confusion et l'angoisse que l'illumination.

Résumé

Il est, en général, une mauvaise idée d'utiliser typedef pour définir un pointeur vers un type de tagless stucture.

Si vous faites cela, vous ne pourrez pas créer des conteneurs STL de const pSomeStruct depuis le compilateur lit comme suit:

list<const pSomeStruct> structs;

list<SomeStruct * const> structs;

qui est pas un conteneur juridique STL puisque les éléments ne sont pas cessibles.

Voir cette question .

Non.

Il fera de votre vie misérable au moment où vous mélangez avec const

typedef foo *fooptr;
const fooptr bar1;
const foo *bar2

Sont bar1 et bar2 le même type?

Et oui, je ne fais que citer Guru Herb Sutter. Une grande vérité at-elle parler. ;)

- Edition -

Ajout lien vers l'article cité.

http://www.drdobbs.com/conversationsa-midsummer-nights -madness / 184403835

API Win32 fait avec à peu près toutes les structures (sinon tous)

POINT => *LPPOINT
WNDCLASSEX => *LPWNDCLASSEX
RECT => *LPRECT
PRINT_INFO_2 => *LPPRINT_INFO_2

Il est bien comment il est cohérent, mais à mon avis, il n'ajoute pas d'élégance.

Le but avec typedef est de cacher les détails de mise en œuvre, mais typedef-ment la propriété pointeur se cache trop et rend le code plus difficile à lire / comprendre. Alors s'il vous plaît ne pas le faire.


Si vous voulez cacher les détails de mise en œuvre (ce qui est souvent une bonne chose à faire), ne cache pas la partie de pointeur. Prenons, par exemple au prototype de l'interface standard de FILE:

FILE *fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, FILE *stream);

ici les retours fopen pointeur à une structure FILE (que vous ne connaissez pas les détails de mise en œuvre). Peut-être FILE est pas un bon exemple parce que dans ce cas, il aurait pu travailler avec un certain type pfile qui cachait le fait qu'il est un pointeur.

pFILE fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, pFILE stream);

Cependant, cela ne fonctionne que parce que vous ne mess avec le contenu qui est pointé directement. Le moment où vous TypeDef un certain pointeur que vous certains endroits modifier le code devient très difficile à lire dans mon expérience.

Il y a quelque temps, je l'aurais répondu « non » à cette question. Maintenant, avec la montée des pointeurs intelligents, les pointeurs ne sont pas toujours définis avec une étoile « * » plus. Donc, il n'y a rien d'évident sur un type d'être un pointeur ou non.

Alors maintenant, je dirais: il est bon de typedef pointeurs, aussi longtemps qu'il est très clair qu'il est un « type de pointeur ». Cela signifie que vous devez utiliser un préfixe / suffixe spécifiquement pour elle. Non, « p » est pas un préfixe suffisant, par exemple. Je serais probablement aller avec "PTR".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top