web-dev-qa-db-fra.com

Quelle est la différence entre une définition et une déclaration?

Le sens des deux m'échappe.

769
Maciek

Un déclaration introduit un identifiant et décrit son type, qu'il s'agisse d'un type, d'un objet ou d'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: 

extern int bar;
extern int g(int, int);
double f(int, double); // extern can be omitted for function declarations
class foo; // no extern allowed for type declarations

Un définition instancie/implémente effectivement cet identifiant. C'est ce dont l'éditeur de liens a besoin afin de lier des références à ces entités. Ce sont des définitions correspondant aux déclarations ci-dessus: 

int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};

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);
extern double f(int, double); // the same as the two above
extern double 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, 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 plus d'une fois, l'éditeur de liens ne connaît pas lequel des définitions pour lier les références et se plaindre des symboles dupliqués. 


Depuis le débat qu'est-ce qu'une classe déclaration vs une classe définition en C++ continue à apparaître (dans les réponses et les commentaires à d'autres questions), je vais coller une citation de la norme C++ ici.
À 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 
— end exemple 

Pour résumer: La norme C++ considère que struct x; est un déclaration et struct x {}; un définition _. (En d'autres termes, "déclaration anticipée" un nom impropre}, puisqu'il n'existe aucune autre forme de déclaration de classe en C++.) 

Merci à litb (Johannes Schaub) qui a extrait le chapitre et le verset dans une de ses réponses. 

782
sbi

A partir de la section 3.1 de la norme C++:

Une déclaration introduit les noms dans une unité de traduction ou redéclare les noms introduits par un fichier .__ précédent. déclarations. Une déclaration spécifie l'interprétation et les attributs de ces noms.

Le paragraphe suivant indique (souligné par moi) qu'une déclaration est une définition sauf si ...

... 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 a
    static int b;  // declares b
};

... il déclare un nom de classe

class Y;

... il contient le mot clé extern sans initialiseur ni corps de fonction

extern const int i = 0;  // defines i
extern int j;  // declares j
extern "C"
{
    void foo();  // declares foo
}

... ou est une déclaration typedef ou using.

typedef long LONG_32;  // declares LONG_32
using namespace std;   // declares std

Maintenant, voici la principale raison pour laquelle il est important de comprendre la différence entre une déclaration et une définition: la règle de définition One. À partir de la section 3.2.1 de la norme C++:

Aucune unité de traduction ne doit contenir plus d'une définition de variable, fonction, type de classe, type d'énumération ou modèle.

162
Michael Kristofik

Déclaration: "Quelque part, il existe un foo."

Définition: "... et le voici!"

125
plinth

Il existe d’intéressants cas Edge en C++ (certains d’entre eux aussi en C). Considérer

T t;

Cela peut être une définition ou une déclaration, selon le type T:

typedef void T();
T t; // declaration of function "t"

struct X { 
  T t; // declaration of function "t".
};

typedef int T;
T t; // definition of object "t".

En C++, lors de l'utilisation de modèles, il existe un autre cas Edge. 

template <typename T>
struct X { 
  static int member; // declaration
};

template<typename T>
int X<T>::member; // definition

template<>
int X<bool>::member; // declaration!

La dernière déclaration é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, 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.
44

Déclaration

Les déclarations indiquent au compilateur qu’un L'élément de programme ou le nom existe. UNE déclaration introduit un ou plusieurs noms dans un programme. Les déclarations peuvent se produire plus d'une fois dans un programme . Par conséquent, les classes, les structures, types énumérés, et autres les types définis par l'utilisateur peuvent être déclarés pour chaque unité de compilation.

Définition

Les définitions spécifient quel code ou quelle donnée le nom décrit. Un nom doit être déclarée avant de pouvoir être utilisée.

31
adatapost

De la norme C99, 6.7 (5):

Une déclaration spécifie l'interprétation et les attributs d'un ensemble d'identifiants. Un definition d'un identifiant est une déclaration pour cet identifiant qui:

  • pour un objet, le stockage est réservé à cet objet;
  • pour une fonction, inclut le corps de la fonction;
  • pour une constante d’énumération ou un nom de typedef, est la (seule) déclaration de l’identifiant

À partir de la norme C++, 3.1 (2):

Une déclaration est un definition sauf si elle déclare une fonction sans spécifier le corps de la fonction, elle contient le spécificateur extern ou une spécification de liaison et ne contient ni initialiseur ni corps de fonction. Elle déclare un membre de données statique dans une déclaration de classe. , c’est une 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.

Donc curieusement (ou pas, mais cela me surprend un peu), typedef int myint; est une définition en C99, mais seulement une déclaration en C++.

20
Steve Jessop

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 variable, ou le type ou la fonction défini par l'utilisateur de votre programme. No l'espace est réservé en mémoire pour toute variable en cas de déclaration. Cependant, le compilateur sait combien d’espace doit être réservé au cas où une variable de ce type serait créée.

par exemple, toutes les déclarations sont les suivantes: 

extern int a; 
struct _tagExample { int a; int b; }; 
int myFunc (int a, int b);

La définition, par contre, signifie qu’en plus de tout ce que fait la déclaration, l’espace est également réservé en mémoire. Vous pouvez dire "DEFINITION = DECLARATION + SPACE RESERVATION" en voici des exemples de définition: 

int a; 
int b = 0; 
int myFunc (int a, int b) { return a + b; } 
struct _tagExample example; 

voir Réponses .

14
Marcin Gil

Mise à jour C++ 11

Puisque je ne vois pas de réponse pertinente pour C++ 11, en voici une.

Une déclaration est une definition sauf si elle déclare un/n:

  • opaque enum - enum X : int;
  • paramètre de modèle - T dans template<typename T> class MyArray;
  • déclaration de paramètre - x et y dans int add(int x, int y);
  • déclaration d'alias - using IntVector = std::vector<int>;
  • déclaration d'assertion statique - static_assert(sizeof(int) == 4, "Yikes!")
  • déclaration d'attribut (défini 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 - add dans int add(int x, int y);
  • spécificateur externe contenant une déclaration ou un spécificateur de liaison - extern int a; ou extern "C" { ... };
  • membre de données statique dans une classe - x dans class C { static int x; };
  • déclaration de classe/struct - struct Point;
  • déclaration typedef - typedef int Int;
  • utiliser la déclaration - using std::cout;
  • using directive - using namespace NS;

Un modèle-déclaration 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 tirés de la norme qui différencie déclaration et définition et que j'ai trouvé utiles pour comprendre les nuances qui les séparent:

// except one all these are definitions
int a;                                  // defines a
extern const int c = 1;                 // defines c
int f(int x) { return x + a; }          // defines f and defines x
struct S { int a; int b; };             // defines S, S::a, and S::b
struct X {                              // defines X
    int x;                              // defines non-static data member x
    static int y;                       // DECLARES static data member y
    X(): x(0) { }                       // defines a constructor of X
};
int X::y = 1;                           // defines X::y
enum { up , down };                     // defines up and down
namespace N { int d; }                  // defines N and N::d
namespace N1 = N;                       // defines N1
X anX;                                  // defines anX


// all these are declarations
extern int a;                           // declares a
extern const int c;                     // declares c
int f(int);                             // declares f
struct S;                               // declares S
typedef int Int;                        // declares Int
extern X anotherX;                      // declares anotherX
using N::d;                             // declares N::d


// specific to C++11 - these are not from the standard
enum X : int;                           // declares X with int as the underlying type
using IntVector = 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 expr
template <class T> class C;             // declares template class C
;                                       // declares nothing
12
legends2k

Déclaration:  

int a; // this declares the variable 'a' which is of type 'int'

Ainsi, la déclaration associe la variable à un type.

Voici quelques exemples de déclaration.

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 pour indiquer qu'il ne s'agit que d'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 ceci 

int b=fun(x,y,z);

Le compilateur générera une erreur en disant 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

#include <stdio.h>
void print(int a)
{
     printf("%d",a);
}
main()
{
    print(5);
}

Dans ce cas, la fonction d'impression est également déclarée et définie. Puisque l'appel de fonction arrive après la définition. Voir maintenant 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);
 }

C'est essentiel parce que 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 s’appelle Définition. Il dit quoi faire dans la fonction. 

void print(int a)
{
    printf("%d",a);
}

Maintenant avec les variables.

int a; //declaration
a=10; //definition 

Parfois, la déclaration et la définition sont regroupées dans une seule déclaration comme celle-ci.

int a=10;
4
Sridharan

définition signifie fonction réelle écrite et déclaration signifie simple déclaration de fonction .__ pour par ex. 

void  myfunction(); //this is simple declaration

et 

void myfunction()
{
 some statement;    
}

c'est la définition de la fonction myfunction 

4
user565367

Pour comprendre les noms, concentrons-nous d'abord sur les verbes.

déclare -pour annoncer officiellement; proclamer

définir - montrer ou décrire (quelqu'un ou quelque chose) clairement et complètement

Donc, quand vous déclarez quelque chose, vous dites simplement ce que c'est.

// declaration
int sum(int, int);

Cette ligne déclare une fonction C appelée sum qui prend deux arguments de type int et renvoie une int. Cependant, vous ne pouvez pas encore l'utiliser.

Lorsque vous indiquez comment cela fonctionne réellement, vous en définissez la définition.

// definition
int sum(int x, int y)
{
    return x + y;
}
3
Karoly Nyisztor

Règle de base:

  • Un 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.

  • Un definition réserve la mémoire pour rendre la variable existante. Cela doit se produire exactement une fois avant le premier accès.

3
bjhend

Trouvez des réponses similaires ici: Questions d'entretien d'embauche à C

Un déclaration fournit un nom au programme; un definition fournit une description unique d'une entité (type, instance et fonction, par exemple) dans le programme. Les déclarations peuvent être répétées dans une portée donnée, cela introduit un nom dans une portée donnée. 

Une déclaration est une définition sauf si

  • Déclaration déclare une fonction sans spécifier son corps,
  • La déclaration contient un spécificateur externe et aucun initialiseur ou corps de fonction,
  • Déclaration est la déclaration d'un membre de données de classe statique sans définition de classe.
  • Déclaration est une définition de nom de classe,

Une définition est une déclaration sauf si:

  • Définition définit un membre de données de classe statique,
  • La définition définit une fonction membre non-inline.
2
Santosh

Ne pourriez-vous pas affirmer, 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 effectivement un stockage à partir d’un identifiant déclaré? 

Une idé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 une déclaration ou une définition? Il doit s'agir d'une déclaration car aucun stockage n'est alloué et vous ne faites que "prototyper" la classe ou la fonction de modèle.

2
user154171

Pour comprendre la différence entre déclaration et définition, nous devons voir le code d'assemblage:

uint8_t   ui8 = 5;  |   movb    $0x5,-0x45(%rbp)
int         i = 5;  |   movl    $0x5,-0x3c(%rbp)
uint32_t ui32 = 5;  |   movl    $0x5,-0x38(%rbp)
uint64_t ui64 = 5;  |   movq    $0x5,-0x10(%rbp)
double   doub = 5;  |   movsd   0x328(%rip),%xmm0        # 0x400a20
                        movsd   %xmm0,-0x8(%rbp)

et ce n'est qu'une définition:

ui8 = 5;   |   movb    $0x5,-0x45(%rbp)
i = 5;     |   movl    $0x5,-0x3c(%rbp)
ui32 = 5;  |   movl    $0x5,-0x38(%rbp)
ui64 = 5;  |   movq    $0x5,-0x10(%rbp)
doub = 5;  |   movsd   0x328(%rip),%xmm0        # 0x400a20
               movsd   %xmm0,-0x8(%rbp)

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:

uint def;                  |  no instructions
printf("some stuff...");   |  [...] callq   0x400450 <printf@plt>
def=5;                     |  movb    $0x5,-0x45(%rbp)

Déclaration n'a pas d'instruction équivalente car ce n'est pas quelque chose à exécuter.

De plus, la déclaration indique au compilateur l'étendue 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 la durée pendant laquelle de la mémoire appartient à une variable.

2
princio

Déclaration signifie donner le nom et le type à une variable (dans le cas d'une déclaration de variable) Exemple: 

 int i;  

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: 

int max(int, int);

alors que définition signifie assigner une valeur à une variable (dans le cas d'une définition de variable) ..__, par exemple:

i = 20;

ou fournir/ajouter un corps (fonctionnalité) à une fonction est appelée définition de fonction.

par exemple: 

 int max(int a, int b)
 {
    if(a>b)   return a;
    return b;  
 }

plusieurs déclarations de temps et définition peuvent être faites ensemble comme:

int i=20;   

et

int max(int a, int b)
{
    if(a>b)   return a;
    return b;    
} 

Dans les cas ci-dessus, nous définissons et déclarons la variable i et la fonction max ()

1
Puneet Purohit

Cela va paraître vraiment ringard, mais c'est la meilleure façon dont j'ai pu garder les termes dans ma tête:

Déclaration: Picture Thomas Jefferson en train de prononcer un discours ... "JE DÉCLARE PAR LA PRÉSENTE QUE CE FOO EXISTE DANS CE CODE SOURCE !!!"

Définition: imaginez un dictionnaire, vous cherchez Foo et ce que cela signifie réellement.

1
It'sPete

Selon le GNU manuel de la bibliothèque C ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )

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. Une définition, en revanche, alloue effectivement le stockage d’une variable ou dit ce que fait une fonction.

1
LinuxBabe

Une déclaration présente un nom de symbole au compilateur. Une définition est une déclaration qui alloue de l'espace pour le symbole.

int f(int x); // function declaration (I know f exists)

int f(int x) { return 2*x; } // declaration and definition
0
hdante

Etapes d'une génération exécutable: 

(1) pré-processeur -> (2) traducteur/compilateur -> (3) éditeur de liens

À l'étape 2 (traducteur/compilateur), les instructions de déclaration de notre code indiquent au compilateur que nous allons utiliser ces éléments à l'avenir et que vous pourrez trouver la définition plus tard, ce qui signifie

traducteur assurez-vous que: qu'est-ce que c'est? 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

0
Jeet Parikh

Il existe 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 à laquelle un stockage est attribué; "déclaration" fait référence aux endroits où la nature de la variable est indiquée mais où aucun stockage n'est alloué. [p. 33]

...

Il est important de distinguer 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 la mise de côté du stockage. Si les lignes

int sp;
double val[MAXVAL]

apparaissent en dehors de toute fonction, elles définissent les variables externes sp et val, provoquent l’annulation du stockage et servent également de déclaration pour le reste du fichier source .

D'autre part, les lignes

extern int sp;
extern double val[];

declare pour le reste du fichier source que sp est un int et que val est un tableau double (dont la taille est déterminée ailleurs) , mais ils ne créent pas les variables ou ne leur réservent pas de stockage.

Il ne doit exister qu'un seul définition d'une variable externe parmi tous les fichiers composant le programme source. ... Les tailles de tableau doivent être spécifiées avec la définition, mais sont facultatives avec une déclaration extern. [pp. 80-81]

...

Les déclarations spécifient 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 le stockage sont appelées définitions. [p. 210]

0
Brad Solomon

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 la valeur cinq nous

  • Définit le type d'un objet, qui peut être intégré ou une classe ou une structure.
  • Déclarez le nom d'un objet. Ainsi, tout ce qui porte un nom a été déclaré, y compris les variables, fonctions, etc.

Une classe ou une structure vous permet de modifier la manière dont les objets seront définis lorsqu’il sera utilisé ultérieurement. Par exemple

  • On peut déclarer une variable ou un tableau hétérogène qui ne sont pas définis spécifiquement.
  • En utilisant un décalage en C++, vous pouvez définir un objet qui n’a pas de nom déclaré.

Lorsque nous apprenons à programmer, ces deux termes sont souvent confondus parce que nous faisons souvent les deux en même temps. 

0
Jason K.

Le concept de déclaration et de définition constituera un écueil lorsque vous utiliserez la classe de stockage externe car votre définition sera à un autre emplacement et vous déclarez la variable dans votre fichier de code local (page). Une différence entre C et C++ est que dans C vous les déclarations sont faites normalement au début d'une page de fonction ou de code. En C++, ce n'est pas comme ça. Vous pouvez déclarer à un endroit de votre choix.

0
achoora