Qual è la differenza tra una definizione e una dichiarazione?

Il significato di entrambi mi sfugge.

Una dichiarazione introduce un identificatore e ne descrive il tipo, sia esso un tipo, un object o una funzione. Una dichiarazione è ciò che il compilatore deve accettare i riferimenti a quell’identificatore. Queste sono dichiarazioni:

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 

Una definizione effettivamente istanzia / implementa questo identificatore. È ciò di cui il linker ha bisogno per colbind riferimenti a tali quadro. Queste sono definizioni corrispondenti alle dichiarazioni di cui sopra:

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

Una definizione può essere utilizzata al posto di una dichiarazione.

Un identificatore può essere dichiarato tutte le volte che vuoi. Pertanto, quanto segue è legale in C e 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); 

Tuttavia, deve essere definito esattamente una volta. Se ti dimentichi di definire qualcosa che è stato dichiarato e referenziato da qualche parte, allora il linker non sa a cosa colbind i riferimenti e si lamenta di un simbolo mancante. Se si definisce qualcosa più di una volta, il linker non sa quale delle definizioni per colbind i riferimenti e si lamenta dei simboli duplicati.


Dal momento che il dibattito su una dichiarazione di class rispetto a una definizione di class in C ++ continua a venire (in risposte e commenti ad altre domande), incollo qui una citazione dallo standard C ++.
Al 3.1 / 2, C ++ 03 dice:

Una dichiarazione è una definizione a meno che […] non sia una dichiarazione di nome di class […].

3.1 / 3 quindi fornisce alcuni esempi. Tra di loro:

 [Esempio: [...]
 struct S {int a;  int b;  };  // definisce S, S :: a e S :: b [...]
 struct S;  // dichiara S
 -End esempio

Per riassumere: lo standard C ++ considera struct x; essere una dichiarazione e struct x {}; una definizione (In altre parole, “dichiarazione anticipata” è un termine improprio , poiché non ci sono altre forms di dichiarazioni di class in C ++.)

Grazie a litb (Johannes Schaub) che ha tirato fuori il capitolo e il verso in una delle sue risposte.

Dalla sezione standard C ++ 3.1:

Una dichiarazione introduce i nomi in un’unità di traduzione o redeclar i nomi introdotti dalle precedenti dichiarazioni. Una dichiarazione specifica l’interpretazione e gli attributi di questi nomi.

Il paragrafo seguente afferma (sottolineatura mia) che una dichiarazione è una definizione a meno che …

… dichiara una funzione senza specificare il corpo della funzione

 void sqrt(double); // declares sqrt 

… dichiara un membro statico all’interno di una definizione di class

 struct X { int a; // defines a static int b; // declares b }; 

… dichiara un nome di class

 class Y; 

… contiene la parola chiave extern senza un inizializzatore o un corpo di funzione

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

… o è un typedef o una dichiarazione d’ using .

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

Ora per la grande ragione per cui è importante capire la differenza tra una dichiarazione e una definizione: la regola della definizione unica . Dalla sezione 3.2.1 dello standard C ++:

Nessuna unità di traduzione deve contenere più di una definizione di qualsiasi variabile, funzione, tipo di class, tipo di enumerazione o modello.

Dichiarazione: “Da qualche parte, esiste un foo”.

Definizione: “… ed eccolo qui!”

Ci sono interessanti casi limite in C ++ (alcuni anche in C). Prendere in considerazione

 T t; 

Può essere una definizione o una dichiarazione, a seconda del tipo 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". 

In C ++, quando si usano i modelli, c’è un altro caso limite.

 template  struct X { static int member; // declaration }; template int X::member; // definition template<> int X::member; // declaration! 

L’ultima dichiarazione non era una definizione. È la dichiarazione di una specializzazione esplicita del membro statico di X . Indica al compilatore: “Se si tratta di istanziare X::member , non istanziare la definizione del membro dal modello primario, ma utilizzare la definizione trovata altrove”. Per renderlo una definizione, devi fornire un inizializzatore

 template<> int X::member = 1; // definition, belongs into a .cpp file. 

Dichiarazione

Le dichiarazioni dicono al compilatore che esiste un elemento o un nome di programma. Una dichiarazione introduce uno o più nomi in un programma. Le dichiarazioni possono verificarsi più volte in un programma. Pertanto, classi, strutture, tipi enumerati e altri tipi definiti dall’utente possono essere dichiarati per ciascuna unità di compilazione.

Definizione

Le definizioni specificano quale codice o dato il nome descrive. Un nome deve essere dichiarato prima di poter essere utilizzato.

Dallo standard C99, 6.7 (5):

Una dichiarazione specifica l’interpretazione e gli attributi di un insieme di identificatori. Una definizione di un identificatore è una dichiarazione per quell’identificatore che:

  • per un object, lo spazio di archiviazione è riservato per quell’object;
  • per una funzione, include il corpo della funzione;
  • per una costante di enumerazione o un nome typedef, è la (solo) dichiarazione dell’identificatore.

Dallo standard C ++, 3.1 (2):

Una dichiarazione è una definizione a meno che non dichiari una funzione senza specificare il corpo della funzione, contiene l’identificatore extern o una specifica di collegamento e né un inizializzatore né un corpo di funzione, dichiara un membro di dati statici in una dichiarazione di class, è un dichiarazione del nome della class, oppure è una dichiarazione typedef, una dichiarazione d’uso o una direttiva using.

Poi ci sono alcuni esempi.

Così interessante (o meno, ma ne sono leggermente sorpreso), typedef int myint; è una definizione in C99, ma solo una dichiarazione in C ++.

Da wiki.answers.com:

Il termine dichiarazione indica (in C) che stai dicendo al compilatore tipo, dimensione e in caso di dichiarazione di funzione, tipo e dimensione dei suoi parametri di qualsiasi variabile, o tipo definito dall’utente o funzione nel tuo programma. Nessuno spazio è riservato in memoria per qualsiasi variabile in caso di dichiarazione. Tuttavia, il compilatore sa quanto spazio riservare nel caso in cui venga creata una variabile di questo tipo.

per esempio, di seguito sono riportate tutte le dichiarazioni:

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

La definizione d’altra parte significa che, oltre a tutte le cose che fa la dichiarazione, lo spazio è anche riservato nella memoria. Puoi dire “DEFINIZIONE = DICHIARAZIONE + PRENOTAZIONE SPAZIO” che seguono sono esempi di definizione:

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

vedi risposte .

Aggiornamento C ++ 11

Dal momento che non vedo una risposta pertinente a C ++ 11 eccone una.

Una dichiarazione è una definizione a meno che non dichiara a / n:

  • opaque enum- enum X : int;
  • parametro template – T nel template class MyArray;
  • dichiarazione dei parametri – x e y in int add(int x, int y);
  • alias declaration – using IntVector = std::vector;
  • dichiarazione di asserzione statica – static_assert(sizeof(int) == 4, "Yikes!")
  • dichiarazione di attributo (definita dall’implementazione)
  • dichiarazione vuota ;

Clausole aggiuntive ereditate da C ++ 03 dall’elenco precedente:

  • dichiarazione di funzione – add in int add(int x, int y);
  • specificatore esterno contenente dichiarazione o specificatore di linkage – extern int a; o extern "C" { ... };
  • membro di dati statici in una class – x in class C { static int x; }; class C { static int x; };
  • dichiarazione di class / struct – struct Point;
  • dichiarazione typedef – typedef int Int;
  • usando la dichiarazione – using std::cout;
  • using directive – using namespace NS;

Una dichiarazione modello è una dichiarazione. Una dichiarazione modello è anche una definizione se la sua dichiarazione definisce una funzione, una class o un membro dati statico.

Esempi tratti dallo standard che distingue tra dichiarazione e definizione che ho trovato utile per comprendere le sfumature tra di loro:

 // 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; // declares IntVector as an alias to std::vector static_assert(X::y == 1, "Oops!"); // declares a static_assert which can render the program ill-formsd or have no effect like an empty declaration, depending on the result of expr template  class C; // declares template class C ; // declares nothing 

definizione significa funzione reale scritta e dichiarazione significa semplice dichiarazione di funzione per es

 void myfunction(); //this is simple declaration 

e

 void myfunction() { some statement; } 

questa è la definizione della funzione miafunzione

Dichiarazione:

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

Pertanto la dichiarazione associa la variabile a un tipo.

Di seguito sono riportati alcuni esempi di dichiarazione.

 int a; float b; double c; 

Ora dichiarazione di funzione:

 int fun(int a,int b); 

Nota il punto e virgola alla fine della funzione, quindi dice che è solo una dichiarazione. Il compilatore sa che da qualche parte nel programma tale funzione verrà definita con quel prototipo. Ora se il compilatore ottiene una funzione chiama qualcosa di simile

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

Il compilatore genera un errore dicendo che non esiste tale funzione. Perché non ha alcun prototipo per quella funzione.

Notare la differenza tra due programmi.

Programma 1

 #include  void print(int a) { printf("%d",a); } main() { print(5); } 

In questo, la funzione di stampa è dichiarata e definita pure. Poiché la chiamata alla funzione viene dopo la definizione. Ora vedi il prossimo programma.

Programma 2

  #include  void print(int a); // In this case this is essential main() { print(5); } void print(int a) { printf("%d",a); } 

È essenziale perché la chiamata alla funzione precede la definizione, quindi il compilatore deve sapere se esiste una tale funzione. Quindi dichiariamo la funzione che informsrà il compilatore.

Definizione:

Questa parte della definizione di una funzione si chiama Definizione. Dice cosa fare all’interno della funzione.

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

Ora con le variabili.

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

Alcune volte la dichiarazione e la definizione sono raggruppate in una singola dichiarazione come questa.

 int a=10; 

Regola del pollice:

  • Una dichiarazione dice al compilatore come interpretare i dati della variabile in memoria. Questo è necessario per ogni accesso.

  • Una definizione riserva la memoria per rendere la variabile esistente. Questo deve accadere esattamente una volta prima del primo accesso.

Non potreste indicare nei termini più generali possibili che una dichiarazione è un identificatore in cui non è allocata alcuna memoria e una definizione effettivamente assegna la memorizzazione a un identificatore dichiarato?

Un pensiero interessante: un modello non può allocare memoria finché la class o la funzione non è collegata con le informazioni sul tipo. Quindi l’identificatore del modello è una dichiarazione o una definizione? Dovrebbe essere una dichiarazione poiché non è allocato spazio di archiviazione e si sta semplicemente “prototipando” la class o la funzione del modello.

Trova risposte simili qui: Domande di intervista tecnica in C

Una dichiarazione fornisce un nome al programma; una definizione fornisce una descrizione univoca di un’entity framework (ad esempio, tipo, istanza e funzione) all’interno del programma. Le dichiarazioni possono essere ripetute in un determinato ambito, introduce un nome in un determinato ambito.

Una dichiarazione è una definizione a meno che

  • Dichiarazione dichiara una funzione senza specificarne il corpo,
  • La dichiarazione contiene uno specificatore esterno e nessun inizializzatore o corpo della funzione,
  • La dichiarazione è la dichiarazione di un membro di dati di class statici senza una definizione di class,
  • La dichiarazione è una definizione di nome di class,

Una definizione è una dichiarazione a meno che:

  • Definizione definisce un membro di dati di class statico,
  • Definizione definisce una funzione membro non in linea.

Dichiarazione significa dare nome e tipo a una variabile (in caso di dichiarazione variabile) ad esempio:

  int i; 

o dare un nome, un tipo di ritorno e un tipo di parametro (s) a una funzione senza corpo (in caso di dichiarazione di funzione)

per esempio:

 int max(int, int); 

mentre definizione significa assegnare valore a una variabile (in caso di definizione di variabile). per esempio:

 i = 20; 

o fornire / aggiungere il corpo (funzionalità) a una funzione è chiamata definizione della funzione.

per esempio:

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

molte dichiarazioni di tempo e definizione possono essere fatte insieme come:

 int i=20; 

e

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

Nei casi di cui sopra definiamo e dichiariamo la variabile i e la funzione max ()

Sembrerà davvero banale, ma è il modo migliore in cui sono riuscito a mantenere i termini nella mia testa:

Dichiarazione: Picture Thomas Jefferson che pronuncia un discorso … “DICHIARO DI QUESTO FOO CHE ESISTE IN QUESTO CODICE SORGENTE !!!”

Definizione: immagina un dizionario, stai cercando Foo e cosa significa in realtà.

Per capire la differenza tra dichiarazione e definizione dobbiamo vedere il codice assembly:

 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) 

e questa è solo una definizione:

 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) 

Come puoi vedere, non cambia nulla.

La dichiarazione è diversa dalla definizione perché fornisce informazioni utilizzate solo dal compilatore. Ad esempio, uint8_t dice al compilatore di usare la funzione asm movb.

Guarda quello:

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

La dichiarazione non ha un’istruzione equivalente perché non è qualcosa da eseguire.

Inoltre la dichiarazione indica al compilatore l’ambito della variabile.

Possiamo dire che la dichiarazione è un’informazione usata dal compilatore per stabilire l’uso corretto della variabile e per quanto a lungo una certa memoria appartiene a certe variabili.

Per capire i nomi, concentriamoci prima sui verbi.

dichiarare – annunciare ufficialmente; proclamare

define – per mostrare o descrivere (qualcuno o qualcosa) in modo chiaro e completo

Quindi, quando dichiari qualcosa, devi solo dire di cosa si tratta .

 // declaration int sum(int, int); 

Questa riga dichiara una funzione C chiamata sum che accetta due argomenti di tipo int e restituisce un int . Tuttavia, non puoi ancora usarlo.

Quando fornisci come funziona , questa è la definizione.

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

Secondo il manuale della libreria GNU C ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )

In C, una dichiarazione fornisce semplicemente informazioni che una funzione o una variabile esiste e dà il suo tipo. Per una dichiarazione di funzione, potrebbero essere fornite anche informazioni sui tipi dei suoi argomenti. Lo scopo delle dichiarazioni è di consentire al compilatore di elaborare correttamente i riferimenti alle variabili e alle funzioni dichiarate. Una definizione, d’altra parte, alloca effettivamente la memoria per una variabile o dice cosa fa una funzione.

Una dichiarazione introduce un nome nel programma; una definizione fornisce una descrizione univoca di un’ quadro (ad esempio, tipo, istanza e funzione). Le dichiarazioni possono essere ripetute in un determinato ambito, introduce un nome in un determinato ambito. Ci deve essere esattamente una definizione di ogni object, funzione o class utilizzata in un programma C ++. Una dichiarazione è una definizione a meno che:

 * it declares a function without specifying its body, * it contains an extern specifier and no initializer or function body, * it is the declaration of a static class data member without a class definition, * it is a class name definition, * it is a typedef declaration. 

Una definizione è una dichiarazione a meno che:

 * it defines a static class data member, * it defines a non-inline member function. 

Differenza tra dichiarare e definire con funzioni: l’istruzione prototype per una funzione lo dichiara, cioè dice al compilatore circa la funzione – il suo nome, tipo di ritorno, e il numero e il tipo dei suoi parametri. L’intestazione della funzione, seguita dal corpo della funzione, definisce la funzione, fornendo i dettagli dei passaggi per eseguire l’operazione della funzione.

Ex.

Codice:

 //Declare int foo(int); //Define int foo(int){ ... } 

Rispetto alle variabili: per le variabili automatiche e di registro, non vi è alcuna differenza tra definizione e dichiarazione. Il processo di dichiarazione di una variabile automatica o di registro definisce il nome della variabile e alloca la memoria appropriata.

Tuttavia, per le variabili esterne: Perché la memoria per una variabile deve essere allocata solo una volta, per garantire che l’accesso alla variabile faccia sempre riferimento alla stessa cella. tutte le variabili devono essere definite una sola volta.

Se una variabile esterna deve essere utilizzata in un file diverso da quello in cui è definita, è necessario un meccanismo per “connettere” tale uso con la cella di variabile esterna definita in modo univoco assegnata per tale file. Questo processo di connessione dei riferimenti della stessa variabile esterna in file diversi, è chiamato risoluzione dei riferimenti.

Può essere definito e dichiarato con una dichiarazione dichiarazione al di fuori di qualsiasi funzione, senza alcun identificatore di class di memoria. Tale dichiarazione alloca la memoria per la variabile. Una dichiarazione di dichiarazione può anche essere utilizzata per dichiarare semplicemente un nome di variabile con lo specificatore di class di archiviazione extern all’inizio della dichiarazione. Tale dichiarazione specifica che la variabile è definita altrove, cioè la memoria per questa variabile è allocata in un altro file. Pertanto, l’accesso a una variabile esterna in un file diverso da quello in cui è definito è ansible se è dichiarato con la parola chiave extern; nessuna nuova memoria è allocata. Tale dichiarazione dice al compilatore che la variabile è definita altrove, e il codice è compilato con la variabile esterna rimasta non risolta. Il riferimento alla variabile esterna viene risolto durante il processo di collegamento.

Ex.

Codice

 //file1.c extern char stack[10]; extern int stkptr; .... //file2.c char stack[10]; int stkptr; .... 

Queste dichiarazioni dicono al compilatore che le variabili stack [] e stkptr sono definite altrove, di solito in qualche altro file. Se la parola chiave extern fosse omessa, le variabili sarebbero considerate come nuove e la memoria sarebbe allocata per loro. Ricorda, l’accesso alla stessa variabile esterna definita in un altro file è ansible solo se la parola chiave extern è utilizzata nella dichiarazione.

Il concetto di Dichiarazione e Definizione si trasformsrà in una trappola quando si utilizza la class di archiviazione extern perché la definizione sarà in un’altra posizione e si dichiara la variabile nel file di codice locale (pagina). Una differenza tra C e C ++ è che in C le dichiarazioni vengono fatte normalmente all’inizio di una funzione o di una tabella codici. In C ++ non è così. Puoi dichiarare in un luogo di tua scelta.

My favorite example is “int Num = 5” here your variable is 1. defined as int 2. declared as Num and 3. instantiated with a value of five. Noi

  • Define the type of an object, which may be built-in or a class or struct.
  • Declare the name of an object, so anything with a name has been declared which includes Variables, Funtions, etc.

A class or struct allows you to change how objects will be defined when it is later used. Per esempio

  • One may declare a heterogeneous variable or array which are not specifically defined.
  • Using an offset in C++ you may define an object which does not have a declared name.

When we learn programming these two terms are often confused because we often do both at the same time.

A declaration presents a symbol name to the compiler. A definition is a declaration that allocates space for the symbol.

 int f(int x); // function declaration (I know f exists) int f(int x) { return 2*x; } // declaration and definition 

A variable is declared when the compiler is informsd that a variable exists (and this is its type); it does not allocate the storage for the variable at that point.

A variable is defined when the compiler allocates the storage for the variable.

Whenever we write function after the main function, compiler will through the error since it does not have any idea about the function at the time of calling function. If we provide prototype declaration of function then we compiler will not look for the definition.

 int sum(int,int); main() { int res = sum(10,20); } int sum(int n1,int n2) { return(n1+n2); } 

In the above example , first line is called as function declaration.

 int sum(int,int); 

Declaring Variable

Whenever we write declaration statement then memory will not be allocated for the variable. Variable declaration will randomly specify the memory location.

 int ivar; float fvar; 

Variable Declaration Vs Definition Differentiation Parameters

A. Space Reservation :

Whenever we declare a variable then space will not be reserved for the variable. Whenever we declare a variable then compiler will not look for other details such as definition of the variable.

Declaration is handy way to write code in which actual memory is not allocated.

 struct book { int pages; float price; char *bname; }; 

In the above declaration memory is not allocated. Whenever we define a variable then memory will be allocated for the variable.

 struct book b1; 

B. What it does ?

  1. Declaration will identify the data type of the identifier.
  2. Definition of the variable will assign some value to it.

As the stages of a compilation

(1) per-processor -> (2) translator -> (3) assembler -> (4) linker

before going to (2) stage (translator/compiler), declaration statements in our code trying to tell to the (2) stage that this things we are going to use in future and you can find definition later, meaning is :

translator make sure that : what is what ? means declaration

and (4) stage (linker) needs definition to bind the things

Linker make sure that : where is what ? means definition