@Lasse: pas vrai. Une définition définit et déclare à la fois ;-)
Steve Jessop
13
Franchement, j'ai eu beaucoup de mal à apprendre ce qui était, donc je n'ai pas trouvé les noms évidents. Je n'ai eu aucun problème avec les significations, juste quels noms associer aux significations.
David Thornley
6
Pourtant, ce n'est pas une question en double, car cela concerne C / C ++, alors que cette autre question concerne tous les langages, ou aucun, en général. Il a juste des réponses en double (car dans cette autre question, certaines réponses ont choisi d'ignorer tout le langage sauf C et / ou C ++).
Steve Jessop
5
@DavidThornley J'utilise cette astuce: une définition donne une description plus fine d'une variable ou d'une fonction donnée. Pour m'en souvenir, je rappelle que le milieu du mot "définition" a une ressemblance avec le mot "plus fin". :)
Marco Leogrande
4
Incroyable combien de merde il y a sur cette question. Va juste montrer à quel point ce langage est mal compris et comment ces malentendus se propagent régulièrement . C'est vraiment triste.
Courses de légèreté en orbite le
Réponses:
858
Une déclaration introduit un identifiant et décrit son type, que ce soit un type, un objet ou une fonction. Une déclaration est ce dont le compilateur a besoin pour accepter les références à cet identifiant. Ce sont des déclarations:
externint bar;externint g(int,int);double f(int,double);// extern can be omitted for function declarationsclass foo;// no extern allowed for type declarations
Une définition instancie / implémente réellement cet identifiant. C'est ce dont l'éditeur de liens a besoin pour lier des références à ces entités. Ce sont des définitions correspondant aux déclarations ci-dessus:
Une définition peut être utilisée à la place d'une déclaration.
Un identifiant peut être déclaré aussi souvent que vous le souhaitez. Ainsi, ce qui suit est légal en C et C ++:
double f(int,double);double f(int,double);externdouble f(int,double);// the same as the two aboveexterndouble f(int,double);
Cependant, il doit être défini exactement une fois. Si vous oubliez de définir quelque chose qui a été déclaré et référencé quelque part, alors l'éditeur de liens ne sait pas à quoi lier les références et se plaint d'un symbole manquant. Si vous définissez quelque chose plusieurs fois, l'éditeur de liens ne sait pas à laquelle des définitions lier les références et se plaint des symboles dupliqués.
Étant donné que le débat sur ce qu'est une déclaration de classe par rapport à une définition de classe en C ++ revient constamment (dans les réponses et les commentaires à d'autres questions), je vais coller ici une citation de la norme C ++.
En 3.1 / 2, C ++ 03 dit:
Une déclaration est une définition, sauf [...] s'il s'agit d'une déclaration de nom de classe [...].
3.1 / 3 donne ensuite quelques exemples. Parmi eux:
[Exemple: [...]
struct S {int a; int b; }; // définit S, S :: a et S :: b [...]
struct S; // déclare S
—Fin exemple
Pour résumer: Le standard C ++ considère struct x;être une déclaration et struct x {};une définition . (En d'autres termes, «déclaration directe» est un terme impropre , car il n'y a pas d'autres formes de déclarations de classe en C ++.)
Merci à litb (Johannes Schaub) qui a creusé le chapitre et le verset dans l'une de ses réponses.
@unknown: soit votre compilateur est cassé, soit vous avez mal copié le code de sbi. Par exemple, 6.7.2 (2) dans N1124: "Toutes les déclarations qui font référence au même objet ou à la même fonction doivent avoir un type compatible; sinon, le comportement n'est pas défini."
Steve Jessop
4
@Brian: "extern int i;" dit que je suis un int quelque part, ne t'en fais pas. "int i;" signifie que i est un int, et son adresse et sa portée sont déterminées ici.
David Thornley
12
@Brian: Tu as tort. extern int iest une déclaration, car elle introduit / spécifie simplement i. Vous pouvez en avoir autant extern int ique vous le souhaitez dans chaque unité de compilation. int i, cependant, est une définition. Il indique l'espace pour l'entier dans cette unité de traduction et conseille à l'éditeur de liens de lier toutes les références à icette entité. Si vous avez plus ou moins qu'une de ces définitions, l'éditeur de liens se plaindra.
sbi
4
@Brian int i;dans le fichier / la portée globale ou la portée de la fonction est une définition à la fois en C et C ++. En C car il alloue du stockage, et en C ++ car il n'a pas le spécificateur externe ou une spécification de liaison. Celles-ci reviennent à la même chose, ce que dit sbi: dans les deux cas, cette déclaration spécifie l'objet auquel toutes les références à "i" dans cette portée doivent être liées.
Steve Jessop
4
@unknown, méfiez-vous que vous ne pouvez pas redéclarer des membres dans la portée de la classe : struct A { double f(int, double); double f(int, double); };invalide, bien sûr. C'est autorisé ailleurs cependant. Il y a quelques endroits où vous pouvez déclarer des choses, mais pas définir aussi: void f() { void g(); }valide, mais pas ce qui suit: void f() { void g() { } };. Qu'est-ce qu'une définition et quelle déclaration a des règles subtiles en ce qui concerne les modèles - méfiez-vous! +1 pour une bonne réponse cependant.
Johannes Schaub - litb
168
De la section standard C ++ 3.1:
Une déclaration introduit des noms dans une unité de traduction ou redéclare des noms introduits par des déclarations précédentes. Une déclaration précise l'interprétation et les attributs de ces noms.
Le paragraphe suivant déclare (je souligne) qu'une déclaration est une définition à moins que ...
... il déclare une fonction sans spécifier le corps de la fonction:
void sqrt(double);// declares sqrt
... il déclare un membre statique dans une définition de classe:
struct X
{int a;// defines astaticint b;// declares b};
... il déclare un nom de classe:
class Y;
... il contient le externmot - clé sans initialiseur ni corps de fonction:
Maintenant, pour la grande raison pour laquelle il est important de comprendre la différence entre une déclaration et une définition: la règle d'une définition . De la section 3.2.1 de la norme C ++:
Aucune unité de traduction ne doit contenir plus d'une définition d'une variable, d'une fonction, d'un type de classe, d'un type d'énumération ou d'un modèle.
"déclare un membre statique dans une définition de classe" - Cela est vrai même si le membre statique est initialisé, n'est-ce pas? Pouvons-nous faire l'exemple struct x {static int b = 3; };?
RJFalconer
@RJFalconer Vous avez raison; l'initialisation ne transforme pas nécessairement une déclaration en définition (contrairement à ce à quoi on pourrait s'attendre; j'ai certainement trouvé cela surprenant). Votre modification de l'exemple est en fait illégale sauf si elle best également déclarée const. Voir stackoverflow.com/a/3536513/1858225 et daniweb.com/software-development/cpp/threads/140739/… .
Kyle Strand
1
C'est intéressant pour moi. Selon votre réponse, il semble qu'en C ++, une déclaration soit aussi une définition (avec des exceptions), alors que dans la norme C, elle est formulée sous un autre angle (C99, section 6.7, Déclarations): "Une définition d'un identifiant est une déclaration pour cet identifiant qui: [suivie de critères pour différents cas] ". Différentes façons de voir les choses, je suppose. :)
Victor Zamanian
La déclaration est pour le compilateur d'accepter un nom (pour dire au compilateur que le nom est légal, le nom est introduit avec l'intention et non une faute de frappe). La définition est l'endroit où un nom et son contenu sont associés. La définition est utilisée par l'éditeur de liens pour lier une référence de nom au contenu du nom.
La déclaration est pour le compilateur d'accepter un nom (pour dire au compilateur que le nom est légal, le nom est introduit avec l'intention et non une faute de frappe). La définition est l'endroit où un nom et son contenu sont associés. La définition est utilisée par l'éditeur de liens pour lier une référence de nom au contenu du nom.
Gab 是 好人
46
Il existe des cas de bord intéressants en C ++ (certains d'entre eux en C aussi). Considérer
T t;
Cela peut être une définition ou une déclaration, selon le type T:
typedefvoid T();
T t;// declaration of function "t"struct X {
T t;// declaration of function "t".};typedefint T;
T t;// definition of object "t".
En C ++, lors de l'utilisation de modèles, il existe un autre cas de bord.
La dernière déclaration n'était pas une définition. C'est la déclaration d'une spécialisation explicite du membre statique de X<bool>. Il indique au compilateur: "S'il s'agit d'instancier X<bool>::member, alors n'instanciez pas la définition du membre à partir du modèle principal, mais utilisez la définition trouvée ailleurs". Pour en faire une définition, vous devez fournir un initialiseur
template<>int X<bool>::member =1;// definition, belongs into a .cpp file.
Les déclarations indiquent au compilateur qu'il existe un élément ou un nom de programme. Une déclaration introduit un ou plusieurs noms dans un programme. Les déclarations peuvent se produire plusieurs fois dans un programme. Par conséquent, des classes, des structures, des types énumérés et d'autres types définis par l'utilisateur peuvent être déclarés pour chaque unité de compilation.
Définition
Les définitions spécifient le code ou les données que le nom décrit. Un nom doit être déclaré avant de pouvoir être utilisé.
Hum, n'est-ce pas que vous pouvez même définir des classes et des énumérations dans chaque unité de compilation? Au moins, j'ai mis des définitions de classe dans mes en-têtes et je les ai inclus partout. Euh, class foo {};c'est une définition de classe , n'est-ce pas?
sbi
1
Oui. Cependant, "class foo;" est une déclaration. Il indique au compilateur que foo est une classe. "class foo {};" est une définition. Il indique au compilateur exactement quel type de classe foo est.
David Thornley
1
Les noms de membres de classe peuvent être utilisés avant d'être déclarés.
Johannes Schaub - litb
1
Ouais, c'est ce que je voulais dire. Vous pouvez donc faire ce qui suit: struct foo {void b () {f (); } void f (); }, f est visible même s'il n'est pas encore déclaré. Cela fonctionne aussi: struct foo {void b (int = bar ()); typedef int bar; } ;. Il est visible avant sa déclaration dans "tous les corps de fonction, arguments par défaut, constructeur ctor-initializers". Pas dans le type de retour :(
Johannes Schaub - litb
1
@litb: Il n'est pas visible avant sa déclaration, c'est seulement que l' utilisation de l'identifiant est déplacée derrière la déclaration. Oui, je sais, l'effet est le même dans de nombreux cas. Mais pas pour tous les cas, c'est pourquoi je pense que nous devrions utiliser l'explication précise. - Oups, attendez. Il est visible dans les arguments par défaut? Eh bien, cela fait sûrement des ravages dans ma compréhension. Bon sang! <pouts>
sbi
22
D'après la norme C99, 6.7 (5):
Une déclaration spécifie l'interprétation et les attributs d'un ensemble d'identifiants. Une définition d'un identifiant est une déclaration pour cet identifiant qui:
pour un objet, fait que le stockage est réservé pour cet objet;
pour une fonction, comprend le corps de la fonction;
pour une constante d'énumération ou un nom typedef, est la (seule) déclaration de l'identifiant.
De la norme C ++, 3.1 (2):
Une déclaration est une définition sauf si elle déclare une fonction sans spécifier le corps de la fonction, elle contient le spécificateur externe ou une spécification de liaison et ni un initialiseur ni un corps de fonction, elle déclare un membre de données statiques dans une déclaration de classe, c'est un déclaration de nom de classe, ou c'est une déclaration typedef, une déclaration using ou une directive using.
Ensuite, il y a quelques exemples.
Il est donc intéressant (ou non, mais je suis légèrement surpris), typedef int myint;une définition en C99, mais seulement une déclaration en C ++.
@onebyone: Concernant le typedef, cela ne signifierait-il pas qu'il pourrait être répété en C ++, mais pas en C99?
sbi
C'est ce qui m'a surpris, et en ce qui concerne une seule unité de traduction, oui, il y a cette différence. Mais il est clair qu'un typedef peut être répété en C99 dans différentes unités de traduction. C n'a pas de "règle de définition unique" explicite comme C ++, donc les règles qu'il a juste le permettent. C ++ a choisi de le changer en déclaration, mais la règle de définition unique répertorie également les types de choses auxquels il s'applique, et typedefs n'en fait pas partie. Ainsi, les répétitions seraient autorisées en C ++ sous l'ODR tel qu'il est libellé, même si un typedef était une définition. Semble inutilement difficile.
Steve Jessop
... mais je suppose que cette liste dans l'ODR répertorie en fait toutes les choses dont il est possible d'avoir des définitions. Si c'est le cas, alors la liste est en fait redondante et est juste là pour être utile.
Steve Jessop
Que dit la définition ODR de la norme sur les définitions de classe? Ils doivent être répétés.
sbi
2
@sbi: ODR dit "(1) Aucune unité de traduction ne doit contenir plus d'une définition d'un type de classe ..." et "(5) Il peut y avoir plus d'une définition d'un type de classe ... dans un programme à condition que chaque définition apparaît dans une unité de traduction différente ", puis certaines exigences supplémentaires qui équivalent à" les définitions sont les mêmes ".
Steve Jessop
17
De wiki.answers.com:
Le terme déclaration signifie (en C) que vous indiquez au compilateur le type, la taille et en cas de déclaration de fonction, le type et la taille de ses paramètres de n'importe quelle variable, ou le type ou la fonction défini par l'utilisateur dans votre programme. Aucun espace n'est réservé en mémoire pour aucune variable en cas de déclaration. Cependant, le compilateur sait combien d'espace à réserver en cas de création d'une variable de ce type.
La définition, d'autre part, signifie qu'en plus de tout ce que fait la déclaration, l'espace est également réservé en mémoire. Vous pouvez dire "DÉFINITION = DÉCLARATION + RÉSERVATION D'ESPACE" ci-dessous sont des exemples de définition:
int a;int b =0;int myFunc (int a,int b){return a + b;}struct _tagExample example;
Cela aussi est faux (bien que beaucoup plus proche que les autres): struct foo {};c'est une définition , pas une déclaration. Une déclaration de fooserait struct foo;. De là, le compilateur ne sait pas combien d'espace à réserver pour les fooobjets.
sbi
1
@Marcin: sbi dit que "le compilateur sait combien d'espace à réserver en cas de création d'une variable de ce type" n'est pas toujours vrai. struct foo;est une déclaration, mais elle n'indique pas au compilateur la taille de foo. J'ajouterais que struct _tagExample { int a; int b; };c'est une définition. Dans ce contexte, il est donc trompeur d'appeler cela une déclaration. Bien sûr, c'est un, car toutes les définitions sont des déclarations, mais vous semblez suggérer que ce n'est pas une définition. C'est une définition de _tagExample.
Steve Jessop
1
@Marcin Gil: Ce qui signifie que le wiki "Answers" n'est pas toujours précis. Je dois voter pour la désinformation ici.
David Thornley
1
Nous apprenons que ce qu'Adatapost a cité est vrai mais ne répond pas (à l'OMI) à la question. Ce que Marcin a cité est faux. Citer les normes est vrai et répond à la question, mais il est très difficile de faire la tête ou la queue.
Steve Jessop
1
@David Thornley - pas de problème :) C'est de cela que parle ce site. Nous sélectionnons et vérifions les informations.
Marcin Gil
13
Mise à jour C ++ 11
Puisque je ne vois pas de réponse pertinente pour C ++ 11, en voici une.
Une déclaration est une définition à moins qu'elle ne déclare un / n:
énumération opaque - enum X : int;
paramètre de modèle - T intemplate<typename T> class MyArray;
déclaration des paramètres - x et y dansint add(int x, int y);
déclaration d'alias - using IntVector = std::vector<int>;
déclaration d'attribut (définie par l'implémentation)
déclaration vide ;
Clauses supplémentaires héritées de C ++ 03 par la liste ci-dessus:
déclaration de fonction - ajouter dansint add(int x, int y);
spécificateur externe contenant une déclaration ou un spécificateur de liaison - extern int a;ouextern "C" { ... };
membre de données statiques dans une classe - x inclass C { static int x; };
déclaration de classe / struct - struct Point;
déclaration typedef - typedef int Int;
en utilisant la déclaration - using std::cout;
en utilisant la directive - using namespace NS;
Une déclaration-modèle est une déclaration. Une déclaration de modèle est également une définition si sa déclaration définit une fonction, une classe ou un membre de données statique.
Exemples de la norme qui différencie la déclaration et la définition que j'ai trouvé utiles pour comprendre les nuances entre eux:
// except one all these are definitionsint a;// defines aexternconstint c =1;// defines cint f(int x){return x + a;}// defines f and defines xstruct S {int a;int b;};// defines S, S::a, and S::bstruct X {// defines Xint x;// defines non-static data member xstaticint y;// DECLARES static data member y
X(): x(0){}// defines a constructor of X};int X::y =1;// defines X::yenum{ up , down };// defines up and downnamespace N {int d;}// defines N and N::dnamespace N1 = N;// defines N1
X anX;// defines anX// all these are declarationsexternint a;// declares aexternconstint c;// declares cint f(int);// declares fstruct S;// declares StypedefintInt;// declares Intextern X anotherX;// declares anotherXusing N::d;// declares N::d// specific to C++11 - these are not from the standardenum X :int;// declares X with int as the underlying typeusingIntVector= std::vector<int>;// declares IntVector as an alias to std::vector<int>static_assert(X::y ==1,"Oops!");// declares a static_assert which can render the program ill-formed or have no effect like an empty declaration, depending on the result of exprtemplate<class T>class C;// declares template class C;// declares nothing
externint a;// Declaration int a;// Definition
a =10// Initializationint b =10;// Definition & Initialization
La définition associe la variable à un type et alloue de la mémoire, tandis que la déclaration spécifie simplement le type mais n'alloue pas de mémoire. La déclaration est plus utile lorsque vous souhaitez référencer la variable avant la définition.
* Ne confondez pas définition et initialisation. Les deux sont différents, l'initialisation donne de la valeur à la variable. Voir l'exemple ci-dessus.
Voici quelques exemples de définition.
int a;float b;double c;
Maintenant , déclaration de fonction:
int fun(int a,int b);
Notez le point-virgule à la fin de la fonction, il indique donc que ce n'est qu'une déclaration. Le compilateur sait que quelque part dans le programme, cette fonction sera définie avec ce prototype. Maintenant, si le compilateur obtient un appel de fonction quelque chose comme ça
int b=fun(x,y,z);
Le compilateur générera une erreur indiquant qu'il n'y a pas une telle fonction. Parce qu'il n'a pas de prototype pour cette fonction.
En cela, la fonction d'impression est également déclarée et définie. Puisque l'appel de fonction vient après la définition. Maintenant, voyez le programme suivant.
Programme 2
#include<stdio.h>void print(int a);// In this case this is essential
main(){
print(5);}void print(int a){
printf("%d",a);}
Il est essentiel car l'appel de fonction précède la définition, le compilateur doit donc savoir s'il existe une telle fonction. Nous déclarons donc la fonction qui informera le compilateur.
Définition:
Cette partie de la définition d'une fonction est appelée Définition. Il indique quoi faire à l'intérieur de la fonction.
int a; //declaration; a=10; //definitionC'est complètement faux. Lorsque l'on parle d'objets de durée de stockage automatique (objets déclarés dans une définition de fonction qui ne sont pas déclarés avec un autre spécificateur de classe de stockage comme extern), ce sont toujours des définitions.
Joey Pabalinas
La principale différence à saisir est qu'une déclaration dit "une chose existe quelque part qui a ces traits (type, etc.)", alors qu'une définition dit "je déclare une chose avec ces traits, et je l'instancie ici comme bien." Étant donné que vous ne pouvez pas déclarer par anticipation des objets de durée de stockage automatique comme ça, ils seront toujours des définitions.
Joey Pabalinas
À l'exception peut-être de cas de coin typedef étranges que j'oublie toujours, une règle de base est que toutes les définitions sont des déclarations. Pensez-y; lorsque vous instanciez quelque chose, vous devez également dire au compilateur que cette chose existe et quels sont ses traits?
Joey Pabalinas
Mis à jour la réponse selon votre premier commentaire. cependant je ne suis pas d'accord avec ce commentaire "quand vous instanciez quelque chose, vous devez aussi dire au compilateur que cette chose existe". Nous ne spécifions pas toujours le type de lhs lors de l'instanciation. Ex: a = 10. Nous ne spécifions aucun "trait" d'un ici.
SRIDHARAN
4
la définition signifie la fonction réelle écrite et la déclaration signifie une simple fonction de déclaration pour par exemple
La déclaration est différente de la définition car elle donne des informations utilisées uniquement par le compilateur. Par exemple, uint8_t indique au compilateur d'utiliser la fonction asm movb.
La déclaration n'a pas d'instruction équivalente car il n'y a rien à exécuter.
De plus, la déclaration indique au compilateur la portée de la variable.
Nous pouvons dire que la déclaration est une information utilisée par le compilateur pour établir l'utilisation correcte de la variable et pour combien de temps une mémoire appartient à une certaine variable.
Ne pourriez-vous pas dire dans les termes les plus généraux possibles, qu'une déclaration est un identifiant dans lequel aucun stockage n'est alloué et qu'une définition alloue réellement du stockage à partir d'un identifiant déclaré?
Une pensée intéressante - un modèle ne peut pas allouer de stockage tant que la classe ou la fonction n'est pas liée aux informations de type. L'identifiant du modèle est-il donc une déclaration ou une définition? Il doit s'agir d'une déclaration car aucun stockage n'est alloué et vous êtes simplement en train de «prototyper» la classe ou la fonction de modèle.
Votre définition n'est pas fausse en soi, mais la «définition de stockage» semble toujours gênante quand il s'agit de définitions de fonctions. En ce qui concerne les modèles: il template<class T> struct foo;s'agit d'une déclaration de modèle , tout comme celle-ci template<class T> void f();. Les définitions de modèle reflètent les définitions de classe / fonction de la même manière. (Notez qu'un nom de modèle n'est pas un type ou un nom de fonction . Un endroit où vous pouvez le voir est lorsque vous ne pouvez pas passer un modèle en tant que paramètre de type d'un autre modèle. Si vous souhaitez transmettre des modèles au lieu de types, vous avez besoin de paramètres de modèle de modèle. )
sbi
Convenu que la «définition de stockage» est maladroite, en particulier en ce qui concerne les définitions de fonction. La déclaration est int foo () et la définition est int foo () {// du code ici ..}. J'ai généralement besoin d'envelopper mon petit cerveau avec des concepts que je connais - le "stockage" est une telle façon de le garder au moins pour moi ... :)
Une déclaration donne un nom au programme; une définition fournit une description unique d'une entité (par exemple, type, instance et fonction) dans le programme. Les déclarations peuvent être répétées dans une étendue donnée, elle introduit un nom dans une étendue donnée.
Une déclaration est une définition sauf si:
La déclaration déclare une fonction sans spécifier son corps,
La déclaration contient un spécificateur externe et aucun initialiseur ni corps de fonction,
La déclaration est la déclaration d'un membre de données de classe statique sans définition de classe,
La déclaration est une définition de nom de classe,
Une définition est une déclaration sauf si:
La définition définit un membre de données de classe statique,
La définition définit une fonction membre non intégrée.
En C, une déclaration fournit simplement des informations sur l'existence d'une fonction ou d'une variable et donne son type. Pour une déclaration de fonction, des informations sur les types de ses arguments peuvent également être fournies. Le but des déclarations est de permettre au compilateur de traiter correctement les références aux variables et fonctions déclarées. En revanche, une définition alloue en fait du stockage à une variable ou indique ce qu'une fonction fait.
Le concept de Déclaration et Définition formera un écueil lorsque vous utilisez la classe de stockage externe car votre définition se trouvera dans un autre emplacement et vous déclarez la variable dans votre fichier de code local (page). Une différence entre C et C ++ est qu'en C vous les déclarations se font normalement au début d'une fonction ou d'une page de code. En C ++, ce n'est pas comme ça. Vous pouvez déclarer au lieu de votre choix.
Je ne comprends pas pourquoi tant de gens ont voté pour la réponse de sbi. J'ai voté contre la réponse de bjhend, qui était assez bonne, concise, précise et beaucoup plus opportune que la mienne. J'étais triste de voir que j'étais la première personne à le faire en 4 ans.
Jason K.
0
Étapes d'une génération exécutable:
(1) pré-processeur -> (2) traducteur / compilateur -> (3) éditeur de liens
Dans l'étape 2 (traducteur / compilateur), les instructions de déclaration dans notre code indiquent au compilateur que ces choses que nous allons utiliser à l'avenir et vous pouvez trouver la définition plus tard, ce qui signifie:
traducteur assurez-vous que: qu'est-ce que quoi? signifie déclaration
et (3) l'étape (l'éditeur de liens) a besoin d'une définition pour lier les choses
Linker assurez-vous que: où est quoi? signifie définition
Il y a des définitions très claires parsemées dans K&R (2e édition); il est utile de les mettre au même endroit et de les lire comme un seul:
"Définition" fait référence à l'endroit où la variable est créée ou affectée au stockage; "déclaration" fait référence aux endroits où la nature de la variable est indiquée mais aucun stockage n'est alloué. [p. 33]
...
Il est important de faire la distinction entre la déclaration d'une variable externe et sa définition . Une déclaration annonce les propriétés d'une variable (principalement son type); une définition entraîne également l'annulation du stockage. Si les lignes
int sp;double val[MAXVAL]
apparaissent en dehors de toute fonction, ils définissent les variables externes spetval entraînent la mise de côté du stockage et servent également de déclaration pour le reste de ce fichier source.
En revanche, les lignes
externint sp;externdouble val[];
déclarer pour le reste du fichier source qui spest un intet qui valest undouble tableau (dont la taille est déterminée ailleurs), mais ils ne créent pas les variables ni ne leur réservent de stockage.
Il ne doit y avoir qu'une seule définition d'une variable externe parmi tous les fichiers qui composent le programme source. ... Les tailles de tableau doivent être spécifiées avec la définition, mais sont facultatives avec unextern déclaration. [pp. 80-81]
...
Les déclarations précisent l'interprétation donnée à chaque identifiant; ils ne réservent pas nécessairement le stockage associé à l'identifiant. Les déclarations qui réservent du stockage sont appelées définitions . [p. 210]
la moyenne réelle de la définition pour attribuer une valeur / un corps à une variable / fonction tandis que la déclaration signifie fournir un nom, un type à une variable / fonction
Puneet Purohit
Vous pouvez définir quelque chose sans lui affecter de valeur.
Courses de légèreté en orbite le
1
Tout comme ceci:int x;
Courses de légèreté en orbite
c'est une déclaration de variable x pas sa définition
Puneet Purohit
2
Non, c'est les deux. Vous confondez définition et initialisation.
Réponses:
Une déclaration introduit un identifiant et décrit son type, que ce soit un type, un objet ou une fonction. Une déclaration est ce dont le compilateur a besoin pour accepter les références à cet identifiant. Ce sont des déclarations:
Une définition instancie / implémente réellement cet identifiant. C'est ce dont l'éditeur de liens a besoin pour lier des références à ces entités. Ce sont des définitions correspondant aux déclarations ci-dessus:
Une définition peut être utilisée à la place d'une déclaration.
Un identifiant peut être déclaré aussi souvent que vous le souhaitez. Ainsi, ce qui suit est légal en C et C ++:
Cependant, il doit être défini exactement une fois. Si vous oubliez de définir quelque chose qui a été déclaré et référencé quelque part, alors l'éditeur de liens ne sait pas à quoi lier les références et se plaint d'un symbole manquant. Si vous définissez quelque chose plusieurs fois, l'éditeur de liens ne sait pas à laquelle des définitions lier les références et se plaint des symboles dupliqués.
Étant donné que le débat sur ce qu'est une déclaration de classe par rapport à une définition de classe en C ++ revient constamment (dans les réponses et les commentaires à d'autres questions), je vais coller ici une citation de la norme C ++.
En 3.1 / 2, C ++ 03 dit:
3.1 / 3 donne ensuite quelques exemples. Parmi eux:
Pour résumer: Le standard C ++ considère
struct x;
être une déclaration etstruct x {};
une définition . (En d'autres termes, «déclaration directe» est un terme impropre , car il n'y a pas d'autres formes de déclarations de classe en C ++.)Merci à litb (Johannes Schaub) qui a creusé le chapitre et le verset dans l'une de ses réponses.
la source
extern int i
est une déclaration, car elle introduit / spécifie simplementi
. Vous pouvez en avoir autantextern int i
que vous le souhaitez dans chaque unité de compilation.int i
, cependant, est une définition. Il indique l'espace pour l'entier dans cette unité de traduction et conseille à l'éditeur de liens de lier toutes les références ài
cette entité. Si vous avez plus ou moins qu'une de ces définitions, l'éditeur de liens se plaindra.int i;
dans le fichier / la portée globale ou la portée de la fonction est une définition à la fois en C et C ++. En C car il alloue du stockage, et en C ++ car il n'a pas le spécificateur externe ou une spécification de liaison. Celles-ci reviennent à la même chose, ce que dit sbi: dans les deux cas, cette déclaration spécifie l'objet auquel toutes les références à "i" dans cette portée doivent être liées.struct A { double f(int, double); double f(int, double); };
invalide, bien sûr. C'est autorisé ailleurs cependant. Il y a quelques endroits où vous pouvez déclarer des choses, mais pas définir aussi:void f() { void g(); }
valide, mais pas ce qui suit:void f() { void g() { } };
. Qu'est-ce qu'une définition et quelle déclaration a des règles subtiles en ce qui concerne les modèles - méfiez-vous! +1 pour une bonne réponse cependant.De la section standard C ++ 3.1:
Le paragraphe suivant déclare (je souligne) qu'une déclaration est une définition à moins que ...
... il déclare une fonction sans spécifier le corps de la fonction:
... il déclare un membre statique dans une définition de classe:
... il déclare un nom de classe:
... il contient le
extern
mot - clé sans initialiseur ni corps de fonction:... ou est une instruction
typedef
orusing
.Maintenant, pour la grande raison pour laquelle il est important de comprendre la différence entre une déclaration et une définition: la règle d'une définition . De la section 3.2.1 de la norme C ++:
la source
struct x {static int b = 3; };
?b
est également déclaréeconst
. Voir stackoverflow.com/a/3536513/1858225 et daniweb.com/software-development/cpp/threads/140739/… .Déclaration: "Quelque part, il existe un foo."
Définition: "... et le voici!"
la source
Il existe des cas de bord intéressants en C ++ (certains d'entre eux en C aussi). Considérer
Cela peut être une définition ou une déclaration, selon le type
T
:En C ++, lors de l'utilisation de modèles, il existe un autre cas de bord.
La dernière déclaration n'était pas une définition. C'est la déclaration d'une spécialisation explicite du membre statique de
X<bool>
. Il indique au compilateur: "S'il s'agit d'instancierX<bool>::member
, alors n'instanciez pas la définition du membre à partir du modèle principal, mais utilisez la définition trouvée ailleurs". Pour en faire une définition, vous devez fournir un initialiseurla source
Déclaration
Définition
la source
class foo {};
c'est une définition de classe , n'est-ce pas?D'après la norme C99, 6.7 (5):
Une déclaration spécifie l'interprétation et les attributs d'un ensemble d'identifiants. Une définition d'un identifiant est une déclaration pour cet identifiant qui:
De la norme C ++, 3.1 (2):
Une déclaration est une définition sauf si elle déclare une fonction sans spécifier le corps de la fonction, elle contient le spécificateur externe ou une spécification de liaison et ni un initialiseur ni un corps de fonction, elle déclare un membre de données statiques dans une déclaration de classe, c'est un déclaration de nom de classe, ou c'est une déclaration typedef, une déclaration using ou une directive using.
Ensuite, il y a quelques exemples.
Il est donc intéressant (ou non, mais je suis légèrement surpris),
typedef int myint;
une définition en C99, mais seulement une déclaration en C ++.la source
typedef
, cela ne signifierait-il pas qu'il pourrait être répété en C ++, mais pas en C99?De wiki.answers.com:
Le terme déclaration signifie (en C) que vous indiquez au compilateur le type, la taille et en cas de déclaration de fonction, le type et la taille de ses paramètres de n'importe quelle variable, ou le type ou la fonction défini par l'utilisateur dans votre programme. Aucun espace n'est réservé en mémoire pour aucune variable en cas de déclaration. Cependant, le compilateur sait combien d'espace à réserver en cas de création d'une variable de ce type.
par exemple, voici toutes les déclarations:
La définition, d'autre part, signifie qu'en plus de tout ce que fait la déclaration, l'espace est également réservé en mémoire. Vous pouvez dire "DÉFINITION = DÉCLARATION + RÉSERVATION D'ESPACE" ci-dessous sont des exemples de définition:
voir Réponses .
la source
struct foo {};
c'est une définition , pas une déclaration. Une déclaration defoo
seraitstruct foo;
. De là, le compilateur ne sait pas combien d'espace à réserver pour lesfoo
objets.struct foo;
est une déclaration, mais elle n'indique pas au compilateur la taille de foo. J'ajouterais questruct _tagExample { int a; int b; };
c'est une définition. Dans ce contexte, il est donc trompeur d'appeler cela une déclaration. Bien sûr, c'est un, car toutes les définitions sont des déclarations, mais vous semblez suggérer que ce n'est pas une définition. C'est une définition de _tagExample.Mise à jour C ++ 11
Puisque je ne vois pas de réponse pertinente pour C ++ 11, en voici une.
Une déclaration est une définition à moins qu'elle ne déclare un / n:
enum X : int;
template<typename T> class MyArray;
int add(int x, int y);
using IntVector = std::vector<int>;
static_assert(sizeof(int) == 4, "Yikes!")
;
Clauses supplémentaires héritées de C ++ 03 par la liste ci-dessus:
int add(int x, int y);
extern int a;
ouextern "C" { ... };
class C { static int x; };
struct Point;
typedef int Int;
using std::cout;
using namespace NS;
Une déclaration-modèle est une déclaration. Une déclaration de modèle est également une définition si sa déclaration définit une fonction, une classe ou un membre de données statique.
Exemples de la norme qui différencie la déclaration et la définition que j'ai trouvé utiles pour comprendre les nuances entre eux:
la source
Définition:
La définition associe la variable à un type et alloue de la mémoire, tandis que la déclaration spécifie simplement le type mais n'alloue pas de mémoire. La déclaration est plus utile lorsque vous souhaitez référencer la variable avant la définition.
* Ne confondez pas définition et initialisation. Les deux sont différents, l'initialisation donne de la valeur à la variable. Voir l'exemple ci-dessus.
Voici quelques exemples de définition.
Maintenant , déclaration de fonction:
Notez le point-virgule à la fin de la fonction, il indique donc que ce n'est qu'une déclaration. Le compilateur sait que quelque part dans le programme, cette fonction sera définie avec ce prototype. Maintenant, si le compilateur obtient un appel de fonction quelque chose comme ça
Le compilateur générera une erreur indiquant qu'il n'y a pas une telle fonction. Parce qu'il n'a pas de prototype pour cette fonction.
Notez la différence entre deux programmes.
Programme 1
En cela, la fonction d'impression est également déclarée et définie. Puisque l'appel de fonction vient après la définition. Maintenant, voyez le programme suivant.
Programme 2
Il est essentiel car l'appel de fonction précède la définition, le compilateur doit donc savoir s'il existe une telle fonction. Nous déclarons donc la fonction qui informera le compilateur.
Définition:
Cette partie de la définition d'une fonction est appelée Définition. Il indique quoi faire à l'intérieur de la fonction.
la source
int a; //declaration; a=10; //definition
C'est complètement faux. Lorsque l'on parle d'objets de durée de stockage automatique (objets déclarés dans une définition de fonction qui ne sont pas déclarés avec un autre spécificateur de classe de stockage comme extern), ce sont toujours des définitions.la définition signifie la fonction réelle écrite et la déclaration signifie une simple fonction de déclaration pour par exemple
et
c'est la définition de la fonction myfunction
la source
Règle générale:
Une déclaration indique au compilateur comment interpréter les données de la variable en mémoire. Ceci est nécessaire pour chaque accès.
Une définition réserve la mémoire pour rendre la variable existante. Cela doit se produire exactement une fois avant le premier accès.
la source
Pour comprendre les noms, concentrons-nous d'abord sur les verbes.
déclarer - annoncer officiellement; proclamer
définir - montrer ou décrire (quelqu'un ou quelque chose) clairement et complètement
Ainsi, lorsque vous déclarez quelque chose, vous dites simplement ce que c'est .
Cette ligne déclare une fonction C appelée
sum
qui prend deux arguments de typeint
et retourne unint
. Cependant, vous ne pouvez pas encore l'utiliser.Lorsque vous indiquez comment cela fonctionne réellement , c'est sa définition.
la source
Pour comprendre la différence entre déclaration et définition, nous devons voir le code assembleur:
et ce n'est qu'une définition:
Comme vous pouvez le voir, rien ne change.
La déclaration est différente de la définition car elle donne des informations utilisées uniquement par le compilateur. Par exemple, uint8_t indique au compilateur d'utiliser la fonction asm movb.
Regarde ça:
La déclaration n'a pas d'instruction équivalente car il n'y a rien à exécuter.
De plus, la déclaration indique au compilateur la portée de la variable.
Nous pouvons dire que la déclaration est une information utilisée par le compilateur pour établir l'utilisation correcte de la variable et pour combien de temps une mémoire appartient à une certaine variable.
la source
Ne pourriez-vous pas dire dans les termes les plus généraux possibles, qu'une déclaration est un identifiant dans lequel aucun stockage n'est alloué et qu'une définition alloue réellement du stockage à partir d'un identifiant déclaré?
Une pensée intéressante - un modèle ne peut pas allouer de stockage tant que la classe ou la fonction n'est pas liée aux informations de type. L'identifiant du modèle est-il donc une déclaration ou une définition? Il doit s'agir d'une déclaration car aucun stockage n'est alloué et vous êtes simplement en train de «prototyper» la classe ou la fonction de modèle.
la source
template<class T> struct foo;
s'agit d'une déclaration de modèle , tout comme celle-citemplate<class T> void f();
. Les définitions de modèle reflètent les définitions de classe / fonction de la même manière. (Notez qu'un nom de modèle n'est pas un type ou un nom de fonction . Un endroit où vous pouvez le voir est lorsque vous ne pouvez pas passer un modèle en tant que paramètre de type d'un autre modèle. Si vous souhaitez transmettre des modèles au lieu de types, vous avez besoin de paramètres de modèle de modèle. )Trouvez des réponses similaires ici: Questions techniques d'entretien en C .
Une déclaration donne un nom au programme; une définition fournit une description unique d'une entité (par exemple, type, instance et fonction) dans le programme. Les déclarations peuvent être répétées dans une étendue donnée, elle introduit un nom dans une étendue donnée.
Une déclaration est une définition sauf si:
Une définition est une déclaration sauf si:
la source
Cela va sembler vraiment ringard, mais c'est la meilleure façon dont j'ai pu garder les termes droits dans ma tête:
Déclaration: Photo Thomas Jefferson prononçant un discours ... "JE DÉCLARE PAR LA PRÉSENTE QUE CE FOO EXISTE DANS CE CODE SOURCE !!!"
Définition: imaginez un dictionnaire, vous recherchez Foo et ce que cela signifie réellement.
la source
Une déclaration présente un nom de symbole au compilateur. Une définition est une déclaration qui alloue de l'espace au symbole.
la source
Selon le manuel de la bibliothèque GNU C ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )
la source
Le concept de Déclaration et Définition formera un écueil lorsque vous utilisez la classe de stockage externe car votre définition se trouvera dans un autre emplacement et vous déclarez la variable dans votre fichier de code local (page). Une différence entre C et C ++ est qu'en C vous les déclarations se font normalement au début d'une fonction ou d'une page de code. En C ++, ce n'est pas comme ça. Vous pouvez déclarer au lieu de votre choix.
la source
Mon exemple préféré est "int Num = 5" ici votre variable est 1. définie comme int 2. déclarée comme Num et 3. instanciée avec une valeur de cinq. nous
Une classe ou une structure vous permet de modifier la façon dont les objets seront définis lors de leur utilisation ultérieure. Par exemple
Lorsque nous apprenons à programmer, ces deux termes sont souvent confondus, car nous faisons souvent les deux en même temps.
la source
Étapes d'une génération exécutable:
Dans l'étape 2 (traducteur / compilateur), les instructions de déclaration dans notre code indiquent au compilateur que ces choses que nous allons utiliser à l'avenir et vous pouvez trouver la définition plus tard, ce qui signifie:
et (3) l'étape (l'éditeur de liens) a besoin d'une définition pour lier les choses
la source
Il y a des définitions très claires parsemées dans K&R (2e édition); il est utile de les mettre au même endroit et de les lire comme un seul:
la source
La déclaration signifie donner un nom et un type à une variable (en cas de déclaration de variable), par exemple:
ou donner le nom, le type de retour et le type de paramètre (s) à une fonction sans corps (en cas de déclaration de fonction), par exemple:
tandis que la définition signifie attribuer une valeur à une variable (en cas de définition de variable), par exemple:
ou fournir / ajouter un corps (fonctionnalité) à une fonction est appelé définition de fonction, par exemple:
plusieurs déclarations de temps et définition peuvent être faites ensemble comme:
et:
Dans les cas ci-dessus, nous définissons et déclarons les variables
i
etfunction max()
.la source
int x;