Domanda

Il significato di entrambi mi sfugge.

È stato utile?

Soluzione

Una dichiarazione introduce un identificatore e ne descrive il tipo, sia esso un tipo, un oggetto o una funzione. Una dichiarazione è ciò di cui il compilatore ha bisogno per accettare 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 in realtà istanzia / implementa questo identificatore. È ciò di cui il linker ha bisogno per collegare riferimenti a tali entità. 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 dimentichi di definire qualcosa che è stato dichiarato e referenziato da qualche parte, il linker non sa a cosa collegare i riferimenti e si lamenta di un simbolo mancante. Se definisci qualcosa più di una volta, il linker non conosce a quale delle definizioni per collegare riferimenti e si lamenta di simboli duplicati.


Dal momento che il dibattito su cosa sia una dichiarazione di classe contro una definizione di classe in C ++ continua ad emergere (nelle risposte e nei commenti ad altre domande), incollerò un citazione dallo standard C ++ qui.
A 3.1 / 2, C ++ 03 dice:

  

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

3.1 / 3 fornisce quindi alcuni esempi. Tra questi:

[Example: [...]
struct S { int a; int b; }; // defines S, S::a, and S::b [...]
struct S; // declares S
—end example

Per riassumere: lo standard C ++ considera struct x; una dichiarazione e struct x {}; una definizione . (In altre parole, & Quot; forward forward & Quot; un termine improprio , poiché non ci sono altre forme di dichiarazioni di classe in C ++.)

Grazie a litb (Johannes Schaub) che hanno estratto il capitolo e il verso in uno dei suoi risposte.

Altri suggerimenti

Dallo standard C ++ sezione 3.1:

  

Una dichiarazione introduce i nomi in un'unità di traduzione o rinnova i nomi introdotti da precedenti   dichiarazioni. Una dichiarazione specifica l'interpretazione e gli attributi di questi nomi.

Il prossimo paragrafo afferma (sottolineatura mia) che una dichiarazione è una definizione a meno che ...

... dichiara una funzione senza specificare la funzione & # 8217; s body:

void sqrt(double);  // declares sqrt

... dichiara un membro statico all'interno di una definizione di classe:

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

... dichiara un nome di classe:

class Y;

... contiene la extern parola chiave senza inizializzatore o corpo della funzione:

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

... oppure è un'istruzione typedef o 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 di una definizione . Dalla sezione 3.2.1 della norma C ++:

  

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

Dichiarazione: " Da qualche parte esiste un foo. "

Definizione: " ... ed eccolo qui! "

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

T t;

Può essere una definizione o una dichiarazione, a seconda del tipo T che è:

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 template, c'è un altro caso limite.

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

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

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

L'ultima dichiarazione era non una definizione. È la dichiarazione di una specializzazione esplicita del membro statico di X<bool>. Indica al compilatore: & Quot; Se si tratta di creare un'istanza X<bool>::member, non creare un'istanza della definizione del membro dal modello principale, ma utilizzare la definizione trovata altrove & Quot ;. Per renderlo una definizione, devi fornire un inizializzatore

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

Dichiarazione

  

Le dichiarazioni indicano al compilatore che a   esiste un elemento o nome del programma. UN   la dichiarazione introduce uno o più   nomi in un programma. Le dichiarazioni possono   si verificano più di una volta in un programma.   Pertanto, classi, strutture,   tipi enumerati e altro   i tipi definiti dall'utente possono essere dichiarati per   ogni unità di compilazione.

Definizione

  

Le definizioni specificano quale codice o dati   il nome descrive. Un nome deve essere   dichiarato prima che possa 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 oggetto, fa sì che la memoria sia riservata per quell'oggetto;
  • per una funzione, include il corpo della funzione;
  • per una costante di enumerazione o nome typedef, è la (sola) dichiarazione di 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 esterno o una specifica di collegamento e né un inizializzatore né un corpo di funzione, dichiara una statica membro di dati in una dichiarazione di classe, è una dichiarazione di nome di classe o è una dichiarazione typedef, una dichiarazione di utilizzo o una direttiva di utilizzo.

Quindi ci sono alcuni esempi.

Così interessante (o no, 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 di tipo, dimensione e in caso di dichiarazione di funzione, tipo e dimensione dei suoi parametri di qualsiasi variabile, o tipo o funzione definiti dall'utente nel tuo programma. Lo spazio No è 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.

ad 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'altro canto significa che oltre a tutto ciò che fa la dichiarazione, lo spazio è anche riservato nella memoria. Puoi dire & Quot; DEFINIZIONE = DICHIARAZIONE + PRENOTAZIONE SPAZIO & Quot; di seguito sono riportati 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

Dato che non vedo una risposta pertinente a C ++ 11 eccone una qui.

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

  • opaque enum - enum X : int;
  • parametro modello - T in template<typename T> class MyArray;
  • dichiarazione dei parametri - x e y in int add(int x, int y);
  • dichiarazione alias - using IntVector = std::vector<int>;
  • 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 - aggiungi in extern int a;
  • identificatore esterno contenente la dichiarazione o un identificatore di collegamento - extern "C" { ... }; o class C { static int x; };
  • membro di dati statici in una classe - x in struct Point;
  • dichiarazione class / struct - typedef int Int;
  • dichiarazione typedef - using std::cout;
  • utilizzando la dichiarazione - using namespace NS;
  • utilizzando la direttiva - <=>

Una dichiarazione modello è una dichiarazione. Una dichiarazione modello è anche una definizione se la sua dichiarazione definisce una funzione, una classe o un membro di dati statici.

Esempi 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<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

definizione indica l'effettiva funzione scritta & amp; dichiarazione significa semplice funzione di dichiarazione per es.

void  myfunction(); //this is simple declaration

e

void myfunction()
{
 some statement;    
}

questa è la definizione della funzione myfunction

Regola empirica:

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

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

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 sarà definita con quel prototipo. Ora se il compilatore riceve una funzione chiama qualcosa del genere

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

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

Nota la differenza tra due programmi.

Programma 1

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

In questo, viene dichiarata e definita anche la funzione di stampa. Poiché la chiamata di funzione sta arrivando dopo la definizione. Ora guarda il prossimo programma.

Programma 2

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

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

Definizione:

Questa parte della definizione di una funzione è chiamata 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 istruzione come questa.

int a=10;

Per capire i nomi, concentriamoci prima sui verbi.

dichiara - annunciare ufficialmente; proclamare

definisci - per mostrare o descrivere (qualcuno o qualcosa) in modo chiaro e completo

Quindi, quando dichiari qualcosa, dici a 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 <=>. Tuttavia, non puoi ancora usarlo.

Quando fornisci come funziona effettivamente , questa è la sua definizione.

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

Per comprendere la differenza tra dichiarazione e definizione, è necessario 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 la 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 nulla cambia.

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

Vedi che:

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

La dichiarazione non ha un'istruzione equivalente perché non deve essere eseguita.

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

Possiamo affermare che la dichiarazione è un'informazione utilizzata dal compilatore per stabilire l'uso corretto della variabile e per quanto tempo parte della memoria appartiene a una determinata variabile.

Non potresti affermare nei termini più generali possibili, che una dichiarazione è un identificatore in cui non è allocata alcuna memoria e una definizione alloca effettivamente la memoria da un identificatore dichiarato?

Un pensiero interessante: un modello non può allocare memoria fino a quando la classe o la funzione non sono collegate alle informazioni sul tipo. Quindi l'identificatore del modello è una dichiarazione o una definizione? Dovrebbe essere una dichiarazione poiché non è stata allocata alcuna memoria e si sta semplicemente "prototipando" la classe o la funzione del modello.

Trova risposte simili qui: Domande di interviste tecniche in C .

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

Una dichiarazione è una definizione a meno che:

  • La dichiarazione dichiara una funzione senza specificarne il corpo,
  • La dichiarazione contiene un identificatore esterno e nessun inizializzatore o corpo della funzione,
  • Dichiarazione è la dichiarazione di un membro di dati di classe statica senza una definizione di classe,
  • La dichiarazione è una definizione di nome di classe,

Una definizione è una dichiarazione a meno che:

  • La definizione definisce un membro di dati della classe statica,
  • La definizione definisce una funzione membro non incorporata.

Questo suonerà davvero di cattivo gusto, ma è il modo migliore in cui sono stato in grado di mantenere i termini nella mia testa:

Dichiarazione: Picture Thomas Jefferson mentre tiene un discorso ... " DECLO QUI CHE QUESTO FOO ESISTE IN QUESTO CODICE SORGENTE !!! "

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

Una dichiarazione presenta un nome simbolo al compilatore. Una definizione è una dichiarazione che alloca spazio per il simbolo.

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

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

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 sull'esistenza di una funzione o variabile e ne fornisce il 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 funzioni dichiarate. Una definizione, d'altra parte, alloca effettivamente l'archiviazione per una variabile o dice cosa fa una funzione.

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

int i;

oppure assegnare nome, tipo di ritorno e tipo di parametro a una funzione senza corpo (in caso di dichiarazione di funzione), ad esempio:

int max(int, int);

considerando che definizione significa assegnare valore a una variabile (in caso di definizione variabile), ad esempio:

i = 20;

o fornire / aggiungere body (funzionalità) a una funzione si chiama definizione di funzione, ad esempio:

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

molte dichiarazioni e definizioni temporali possono essere fatte insieme come:

int i=20;

e

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

Nei casi precedenti definiamo e dichiariamo le variabili i e function max().

Il concetto di Dichiarazione e Definizione costituirà una trappola quando si utilizza la classe di archiviazione esterna perché la definizione si troverà in un'altra posizione e si sta dichiarando la variabile nel file di codice locale (pagina). Una differenza tra C e C ++ è che in C le dichiarazioni sono fatte normalmente all'inizio di una funzione o di una tabella codici. In C ++ non è così. Puoi dichiarare in un luogo di tua scelta.

Il mio esempio preferito è " int Num = 5 " qui la tua variabile è 1. definita come int 2. dichiarata come Num e 3. istanziata con un valore di cinque. Noi

  • Definisce il tipo di un oggetto, che può essere incorporato o una classe o struttura.
  • Dichiara il nome di un oggetto, quindi è stato dichiarato qualsiasi cosa con un nome che includa Variabili, Funtions, ecc.

Una classe o struttura ti consente di cambiare il modo in cui gli oggetti saranno definiti quando verrà usato in seguito. Ad esempio

  • Si può dichiarare una variabile o matrice eterogenea che non sono specificamente definiti.
  • Usando un offset in C ++ puoi definire un oggetto che non ha un nome dichiarato.

Quando impariamo a programmare questi due termini sono spesso confusi perché spesso facciamo entrambi allo stesso tempo.

Fasi di una generazione eseguibile:

  

(1) pre-processore - > (2) traduttore / compilatore - & Gt; (3) linker

Nella fase 2 (traduttore / compilatore), le dichiarazioni di dichiarazione nel nostro codice dicono al compilatore che queste cose useremo in futuro e puoi trovare la definizione in seguito, il che significa:

  

traduttore assicurati che: che cosa è cosa? significa dichiarazione

e (3) stage (linker) hanno bisogno di definizione per legare le cose

  

Linker assicurati che: dov'è cosa? significa definizione

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top