1045 votes

Définitions de typedef struct et de struct

Je suis un débutant en programmation C, mais je me demandais quelle est la différence entre l'utilisation de typedef lors de la définition d'une structure par rapport à la non-utilisation de typedef . Il me semble qu'il n'y a pas vraiment de différence, ils accomplissent le même but.

struct myStruct{
    int one;
    int two;
};

vs.

typedef struct{
    int one;
    int two;
}myStruct;

0 votes

Je viens de lire, ici sur SO, que la deuxième option donnerait une erreur de compilateur ? ! "passage d'un argument de type pointeur incompatible" stackoverflow.com/questions/12708897/

8 votes

On peut trouver une meilleure réponse (à mon avis) aquí .

1342voto

L'idiome commun est d'utiliser les deux :

typedef struct S { 
    int x; 
} S;

Il s'agit de définitions différentes. Pour rendre la discussion plus claire, je vais diviser la phrase :

struct S { 
    int x; 
};

typedef struct S S;

Dans la première ligne, vous définissez l'identifiant S dans l'espace de nom struct (pas au sens de C++). Vous pouvez l'utiliser et définir des variables ou des arguments de fonction du type nouvellement défini en définissant le type de l'argument comme suit struct S :

void f( struct S argument ); // struct is required here

La deuxième ligne ajoute un alias de type S dans l'espace global des noms et permet ainsi d'écrire simplement :

void f( S argument ); // struct keyword no longer needed

Notez que puisque les deux espaces de noms d'identifiants sont différents, la définition de S à la fois dans les espaces structs et global n'est pas une erreur, car il ne s'agit pas de redéfinir le même identifiant, mais plutôt de créer un identifiant différent à un endroit différent.

Pour que la différence soit plus claire :

typedef struct S { 
    int x; 
} T;

void S() { } // correct

//void T() {} // error: symbol T already defined as an alias to 'struct S'

Vous pouvez définir une fonction avec le même nom que la structure car les identifiants sont conservés dans des espaces différents, mais vous ne pouvez pas définir une fonction avec le même nom qu'un typedef lorsque ces identifiants entrent en collision.

En C++, c'est légèrement différent car les règles pour localiser un symbole ont subtilement changé. Le C++ conserve les deux espaces d'identification différents, mais contrairement au C, lorsque vous définissez le symbole uniquement dans l'espace d'identification de classe, vous n'êtes pas tenu de fournir le mot-clé struct/class :

 // C++
struct S { 
    int x; 
}; // S defined as a class

void f( S a ); // correct: struct is optional

Ce qui change, ce sont les règles de recherche, et non l'endroit où les identifiants sont définis. Le compilateur va chercher dans la table des identificateurs globaux et après S n'a pas été trouvé, il cherchera S dans les identifiants de classe.

Le code présenté précédemment se comporte de la même manière :

typedef struct S { 
    int x; 
} T;

void S() {} // correct [*]

//void T() {} // error: symbol T already defined as an alias to 'struct S'

Après la définition de la S dans la deuxième ligne, la fonction struct S ne peuvent pas être résolus automatiquement par le compilateur, et pour créer un objet ou définir un argument de ce type, vous devez revenir à l'inclusion de la balise struct mot-clé :

// previous code here...
int main() {
    S(); 
    struct S s;
}

69 votes

Excellente réponse qui me montre aussi pourquoi je veux typedef, afin qu'il ne puisse pas être écrasé comme une fonction, merci : ).

12 votes

@AlexanderVarwijk : Vous voulez typedef pour éviter la nécessité de qualifier avec struct o enum . Si les conventions de dénomination que vous utilisez permettent de nommer une fonction et un type par le même nom, le mieux que vous puissiez faire est de revoir la façon dont vous nommez les éléments de votre programme.

1 votes

Mes conventions de nommage devraient permettre d'éviter cela, mais mieux vaut prévenir que guérir : ).

98voto

R Samuel Klatchko Points 44549

Une autre différence qui n'a pas été soulignée est que donner un nom à la structure (par exemple struct myStruct) vous permet également de fournir des déclarations directes de la structure. Ainsi, dans un autre fichier, vous pourriez écrire :

struct myStruct;
void doit(struct myStruct *ptr);

sans avoir besoin d'avoir accès à la définition. Ce que je recommande, c'est de combiner vos deux exemples :

typedef struct myStruct{
    int one;
    int two;
} myStruct;

Cela vous donne la commodité du nom plus concis de typedef mais vous permet toujours d'utiliser le nom complet de struct si vous avez besoin.

2 votes

Il existe des moyens de faire des déclarations anticipées avec typedef : typedef struct myStruct myStruct; ; et ensuite (plus tard) : struct myStruct { ... }; . Vous pouvez l'utiliser comme soit struct myStruct ou juste myStruct après cela typedef (mais le type est incomplet jusqu'à cette définition).

0 votes

Il convient également de mentionner que le C++, bien que (conceptuellement) les balises soient auto-typées et qu'il mette les deux balises struct SomeThing y Something dans un seul "espace de symboles", prévoit explicitement la possibilité d'un contrôle manuel. typedef SomeThing à redéfinir en struct SomeThing ... alors que l'on pourrait supposer que cela générerait une erreur de conflit de noms. Source : stackoverflow.com/a/22386307/2757035 Je suppose que cela a été fait pour des raisons de rétrocompatibilité (un peu futile !).

0 votes

@underscore_d : À l'époque, les gens reconnaissaient l'intérêt de disposer d'un code qui pouvait fonctionner aussi bien en C et en C++, et voulaient éviter de créer des obstacles inutiles à la compatibilité. Malheureusement, cette façon de penser n'est plus à la mode.

73voto

Mehrdad Afshari Points 204872

En C (pas en C++), vous devez déclarer des variables struct comme :

struct myStruct myVariable;

Afin d'être en mesure d'utiliser myStruct myVariable; à la place, vous pouvez typedef la structure :

typedef struct myStruct someStruct;
someStruct myVariable;

Vous pouvez combiner struct définition et typedef dans une seule instruction qui déclare un fichier anonyme de type struct y typedef C'est ça.

typedef struct { ... } myStruct;

1 votes

Le dernier bloc de code n'est pas équivalent au code précédent. Dans la dernière ligne, vous définissez un alias de type 'myStruct' dans une structure non nommée. Il y a des différences (très) subtiles entre les deux versions.

5 votes

Dribeas : J'ai couvert cette différence subtile dans la phrase "...une seule déclaration qui déclare...". une structure anonyme et..."

0 votes

@DavidRodríguez-dribeas Pouvez-vous nous en dire plus sur les différences subtiles ?

25voto

Christoph Points 64389

En C, les mots-clés du spécificateur de type des structures, unions et énumérations sont obligatoires, c'est-à-dire que vous devez toujours préfixer le nom du type (son étiquette ) avec struct , union o enum lorsqu'on se réfère au type.

Vous pouvez vous débarrasser des mots clés en utilisant un typedef Il s'agit d'une forme de dissimulation de l'information, car le type réel d'un objet ne sera plus visible lors de sa déclaration.

Il est donc recommandé (voir par exemple le Guide de style de codage du noyau Linux chapitre 5) de ne le faire que lorsque vous veulent pour cacher cette information et pas seulement pour économiser quelques frappes de clavier.

Un exemple de cas où vous devez utiliser un typedef serait un type opaque qui n'est jamais utilisé qu'avec les fonctions d'accès/macros correspondantes.

4 votes

Guide de style de codage du noyau Linux pour référence : kernel.org/doc/Documentation/CodingStyle

4 votes

Le document sur le style de codage du noyau Linux a été déplacé vers le site suivant kernel.org/doc/Documentation/process/coding-style.rst

6voto

RC. Points 15804

El typedef comme pour les autres constructions, est utilisé pour donner un nouveau nom à un type de données. Dans ce cas, cela est surtout fait pour rendre le code plus propre :

struct myStruct blah;

vs.

myStruct blah;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X