Was ist der Unterschied zwischen einer Definition und einer Erklärung?


857

Die Bedeutung von beiden entgeht mir.


91
@Lasse: nicht wahr. Eine Definition definiert und deklariert ;-)
Steve Jessop

13
Ehrlich gesagt hatte ich große Probleme zu lernen, was das war, also fand ich die Namen nicht offensichtlich. Ich hatte kein Problem mit den Bedeutungen, nur welche Namen mit den Bedeutungen assoziiert werden sollten.
David Thornley

6
Es handelt sich jedoch nicht um eine doppelte Frage, da hier nach C / C ++ gefragt wird, während diese andere Frage nach allen Sprachen oder nach keiner im Allgemeinen gestellt wird. Es gibt nur doppelte Antworten (da in dieser anderen Frage einige Antworten alle Sprachen außer C und / oder C ++ ignorierten).
Steve Jessop

5
@DavidThornley ich diesen Trick anwenden: eine Definition gibt eine feinere Beschreibung einer bestimmten Variablen oder Funktion. Um mich daran zu erinnern, erinnere ich mich, dass die Mitte des Wortes "Definition" dem Wort "feiner" ähnelt. :)
Marco Leogrande

4
Erstaunlich, wie viel Mist es auf dieser Frage gibt. Nur um zu zeigen, wie sehr diese Sprache missverstanden wird und wie diese Missverständnisse routinemäßig verbreitet werden . Es ist wirklich traurig.
Leichtigkeitsrennen im Orbit

Antworten:


858

Eine Deklaration führt einen Bezeichner ein und beschreibt dessen Typ, sei es ein Typ, ein Objekt oder eine Funktion. Eine Deklaration ist das, was der Compiler benötigt , um Verweise auf diesen Bezeichner zu akzeptieren. Dies sind Erklärungen:

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

Eine Definition instanziiert / implementiert diesen Bezeichner tatsächlich. Es ist das, was der Linker benötigt , um Verweise auf diese Entitäten zu verknüpfen. Dies sind Definitionen, die den obigen Erklärungen entsprechen:

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

Eine Definition kann anstelle einer Erklärung verwendet werden.

Ein Bezeichner kann beliebig oft deklariert werden . Daher ist in C und C ++ Folgendes zulässig:

double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);

Es muss jedoch genau einmal definiert werden. Wenn Sie vergessen, etwas zu definieren, das irgendwo deklariert und referenziert wurde, weiß der Linker nicht, worauf er verweisen soll, und beschwert sich über fehlende Symbole. Wenn Sie etwas mehr als einmal definieren, weiß der Linker nicht, auf welche der Definitionen Verweise verweisen sollen, und beschwert sich über doppelte Symbole.


Da die Debatte , was eine Klasse Erklärung gegenüber einer Klassendefinition in C ++ kommen hält (in Antworten und Kommentaren zu anderen Fragen), werde ich ein Zitat aus dem C ++ Standard einfügen hier.
Bei 3.1 / 2 sagt C ++ 03:

Eine Deklaration ist eine Definition, es sei denn, es handelt sich um eine [...] Klassennamendeklaration.

3.1 / 3 gibt dann einige Beispiele. Unter ihnen:

[Beispiel: [...]
struct S {int a; int b; }; // definiert S, S :: a und S :: b [...]
Struktur S; // deklariert S.
- Beispiel beenden

Um es zusammenzufassen: Der C ++ - Standard betrachtet struct x;eine Deklaration und struct x {};eine Definition . (Mit anderen Worten, "Vorwärtsdeklaration" ist eine Fehlbezeichnung , da es in C ++ keine anderen Formen von Klassendeklarationen gibt.)

Vielen Dank an litb (Johannes Schaub), der das eigentliche Kapitel und den Vers in einer seiner Antworten ausgegraben hat.


2
@unknown: Entweder ist Ihr Compiler kaputt, oder Sie haben den Code von sbi falsch kopiert. Beispiel: 6.7.2 (2) in N1124: "Alle Deklarationen, die sich auf dasselbe Objekt oder dieselbe Funktion beziehen, müssen einen kompatiblen Typ haben. Andernfalls ist das Verhalten undefiniert."
Steve Jessop

4
@Brian: "extern int i;" sagt, dass ich irgendwo ein Int bin, mach dir keine Sorgen. "int i;" bedeutet, dass i ein int ist und seine Adresse und sein Umfang hier bestimmt werden.
David Thornley

12
@ Brian: Du liegst falsch. extern int iist eine Deklaration, da sie nur einführt / spezifiziert i. Sie können so viele extern int iin jeder Kompilierungseinheit haben, wie Sie möchten. int iist jedoch eine Definition. Es bezeichnet den Platz für die Ganzzahl in dieser Übersetzungseinheit und empfiehlt dem Linker, alle Verweise auf idiese Entität zu verknüpfen . Wenn Sie mehr oder weniger als genau eine dieser Definitionen haben, wird sich der Linker beschweren.
sbi

4
@Brian int i;im Datei- / globalen Bereich oder Funktionsbereich ist eine Definition sowohl in C als auch in C ++. In C, weil es Speicher zuweist, und in C ++, weil es keinen externen Bezeichner oder keine Verknüpfungsspezifikation hat. Diese belaufen sich auf dasselbe, was sbi sagt: In beiden Fällen gibt diese Deklaration das Objekt an, mit dem alle Verweise auf "i" in diesem Bereich verknüpft werden müssen.
Steve Jessop

4
@unknown, Vorsicht, Sie können Mitglieder im Klassenbereich nicht neu deklarieren : struct A { double f(int, double); double f(int, double); };natürlich ungültig. Es ist aber woanders erlaubt. Es gibt einige Stellen, an denen Sie Dinge deklarieren, aber auch nicht definieren können: void f() { void g(); }gültig, aber nicht die folgenden : void f() { void g() { } };. Was ist eine Definition und was für eine Deklaration gibt es subtile Regeln, wenn es um Vorlagen geht - Vorsicht! +1 für eine gute Antwort.
Johannes Schaub - litb

168

Aus dem C ++ - Standardabschnitt 3.1:

Eine Deklaration führt Namen in eine Übersetzungseinheit ein oder deklariert Namen, die durch frühere Deklarationen eingeführt wurden. Eine Deklaration gibt die Interpretation und Attribute dieser Namen an.

Der nächste Absatz besagt (Hervorhebung von mir), dass eine Erklärung eine Definition ist, es sei denn ...

... deklariert eine Funktion ohne Angabe des Funktionskörpers:

void sqrt(double);  // declares sqrt

... deklariert ein statisches Mitglied innerhalb einer Klassendefinition:

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

... es deklariert einen Klassennamen:

class Y;

... enthält das externSchlüsselwort ohne Initialisierer oder Funktionskörper:

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

... oder ist eine typedefoder usingAussage.

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

Aus dem großen Grund, warum es wichtig ist, den Unterschied zwischen einer Deklaration und einer Definition zu verstehen: die Ein-Definition-Regel . Aus Abschnitt 3.2.1 des C ++ - Standards:

Keine Übersetzungseinheit darf mehr als eine Definition einer Variablen, Funktion, eines Klassentyps, eines Aufzählungstyps oder einer Vorlage enthalten.


"deklariert ein statisches Element innerhalb einer Klassendefinition" - Dies gilt auch dann, wenn das statische Element initialisiert ist, richtig? Können wir das Beispiel machen struct x {static int b = 3; };?
RJFalconer

@RJFalconer Du hast recht; Die Initialisierung macht aus einer Deklaration nicht unbedingt eine Definition (entgegen den Erwartungen; ich fand das sicherlich überraschend). Ihre Änderung am Beispiel ist tatsächlich illegal, sofern nicht bauch deklariert const. Siehe stackoverflow.com/a/3536513/1858225 und daniweb.com/software-development/cpp/threads/140739/… .
Kyle Strand

1
Das ist interessant für mich. Ihrer Antwort zufolge scheint eine Deklaration in C ++ auch eine Definition zu sein (mit Ausnahmen), während sie im C-Standard aus der anderen Perspektive formuliert ist (C99, Abschnitt 6.7, Deklarationen): "Eine Definition eines Bezeichners ist eine Erklärung für diesen Bezeichner, dass: [gefolgt von Kriterien für verschiedene Fälle] ". Ich nehme an, es gibt verschiedene Sichtweisen. :)
Victor Zamanian

Die Erklärung ist, dass der Compiler einen Namen akzeptiert (um dem Compiler mitzuteilen, dass der Name legal ist, wird der Name mit der Absicht eingeführt, kein Tippfehler zu sein). Bei der Definition werden ein Name und sein Inhalt zugeordnet. Die Definition wird vom Linker verwendet, um einen Namensverweis auf den Inhalt des Namens zu verknüpfen.
Gab

137

Erklärung: "Irgendwo gibt es ein Foo."

Definition: "... und hier ist es!"


3
Die Erklärung ist, dass der Compiler einen Namen akzeptiert (um dem Compiler mitzuteilen, dass der Name legal ist, wird der Name mit der Absicht eingeführt, kein Tippfehler zu sein). Bei der Definition werden ein Name und sein Inhalt zugeordnet. Die Definition wird vom Linker verwendet, um einen Namensverweis auf den Inhalt des Namens zu verknüpfen.
Gab

46

Es gibt interessante Randfälle in C ++ (einige davon auch in C). Erwägen

T t;

Dies kann eine Definition oder eine Deklaration sein, je nachdem, um welchen Typ es sich Thandelt:

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 ++ gibt es bei Verwendung von Vorlagen einen anderen Randfall.

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

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

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

Die letzte Erklärung war keine Definition. Es ist die Erklärung einer expliziten Spezialisierung des statischen Mitglieds von X<bool>. Es sagt dem Compiler: "Wenn es um das Instanziieren geht, instanziieren X<bool>::memberSie nicht die Definition des Elements aus der primären Vorlage, sondern verwenden Sie die Definition, die an anderer Stelle gefunden wurde." Um eine Definition zu erstellen, müssen Sie einen Initialisierer angeben

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

35

Erklärung

Deklarationen teilen dem Compiler mit, dass ein Programmelement oder ein Programmname vorhanden ist. Eine Deklaration führt einen oder mehrere Namen in ein Programm ein. Deklarationen können in einem Programm mehrmals vorkommen. Daher können Klassen, Strukturen, Aufzählungstypen und andere benutzerdefinierte Typen für jede Kompilierungseinheit deklariert werden.

Definition

Definitionen geben an, welchen Code oder welche Daten der Name beschreibt. Ein Name muss deklariert werden, bevor er verwendet werden kann.


Ist es nicht so, dass Sie in jeder Kompilierungseinheit sogar Klassen und Aufzählungen definieren können ? Wenigstens habe ich Klassendefinitionen in meine Header und schließen sie alle über. Er, class foo {}; ist eine Klasse Definition , ist es nicht?
sbi

1
Ja. Allerdings "Klasse foo;" ist eine Erklärung. Es teilt dem Compiler mit, dass foo eine Klasse ist. "class foo {};" ist eine Definition. Es sagt dem Compiler genau, was für eine Klasse foo ist.
David Thornley

1
Die Ausnahme bilden Klassenmitgliedsnamen, die verwendet werden können, bevor sie deklariert werden.
Johannes Schaub - litb

1
Ja, das habe ich gemeint. Sie können also Folgendes tun: struct foo {void b () {f (); } void f (); }, f ist sichtbar, obwohl noch nicht deklariert. Folgendes funktioniert auch: struct foo {void b (int = bar ()); typedef int bar; };. Es ist vor seiner Deklaration in "Alle Funktionskörper, Standardargumente, Konstruktor-Ctor-Initialisierer" sichtbar. Nicht im Rückgabetyp :(
Johannes Schaub - litb

1
@litb: Es ist nicht sichtbar, bevor es deklariert wird. Es ist nur so, dass die Verwendung des Bezeichners hinter die Deklaration verschoben wird. Ja, ich weiß, der Effekt ist in vielen Fällen der gleiche. Aber nicht für alle Fälle, weshalb ich denke, wir sollten die genaue Erklärung verwenden. - Ups, warte. Ist es in Standardargumenten sichtbar? Nun, das bringt sicherlich Chaos mit meinem Verständnis. Teufel noch mal! <pouts>
sbi

22

Aus dem C99-Standard 6,7 (5):

Eine Deklaration gibt die Interpretation und Attribute einer Reihe von Bezeichnern an. Eine Definition eines Bezeichners ist eine Deklaration für diesen Bezeichner, die:

  • bewirkt für ein Objekt, dass der Speicher für dieses Objekt reserviert wird;
  • schließt für eine Funktion den Funktionskörper ein;
  • Für eine Aufzählungskonstante oder einen typedef-Namen ist die (einzige) Deklaration des Bezeichners.

Aus dem C ++ - Standard, 3.1 (2):

Eine Deklaration ist eine Definition, es sei denn, sie deklariert eine Funktion ohne Angabe des Funktionskörpers, enthält den externen Bezeichner oder eine Verknüpfungsspezifikation und weder einen Initialisierer noch einen Funktionskörper. Sie deklariert ein statisches Datenelement in einer Klassendeklaration Klassennamendeklaration oder eine typedef-Deklaration, eine using-Deklaration oder eine using-Direktive.

Dann gibt es einige Beispiele.

Interessanterweise (oder auch nicht, aber ich bin etwas überrascht) typedef int myint;ist eine Definition in C99, aber nur eine Deklaration in C ++.


@onebyone: typedefWürde das nicht bedeuten, dass es in C ++ wiederholt werden könnte, aber nicht in C99?
sbi

Das hat mich überrascht, und was eine einzelne Übersetzungseinheit betrifft, gibt es diesen Unterschied. Es ist jedoch klar, dass ein typedef in C99 in verschiedenen Übersetzungseinheiten wiederholt werden kann. C hat keine explizite "One-Definition-Regel" wie C ++, daher erlauben die Regeln dies nur. C ++ hat es in eine Deklaration geändert, aber auch die One-Definition-Regel listet auf, auf welche Art von Dingen es angewendet wird, und typedefs gehört nicht dazu. Daher wären Wiederholungen in C ++ unter dem ODR, wie es formuliert ist, zulässig, selbst wenn ein typedef eine Definition wäre. Scheint unnötig wählerisch.
Steve Jessop

... aber ich würde vermuten, dass diese Liste im ODR tatsächlich alle Dinge auflistet, von denen es möglich ist, Definitionen zu haben. Wenn ja, dann ist die Liste tatsächlich redundant und nur dazu da, hilfreich zu sein.
Steve Jessop

Was sagt die ODR-Definition des Standards über Klassendefinitionen aus? Sie müssen wiederholt werden.
sbi

2
@sbi: ODR sagt "(1) Keine Übersetzungseinheit darf mehr als eine Definition eines ... Klassentyps enthalten" und "(5) Es kann mehr als eine Definition eines Klassentyps ... in einem Programm geben, vorausgesetzt, dass Jede Definition erscheint in einer anderen Übersetzungseinheit "und dann einige zusätzliche Anforderungen, die sich auf" die Definitionen sind gleich "belaufen.
Steve Jessop

17

Von wiki.answers.com:

Der Begriff Deklaration bedeutet (in C), dass Sie dem Compiler Typ, Größe und im Falle einer Funktionsdeklaration Typ und Größe seiner Parameter einer Variablen oder eines benutzerdefinierten Typs oder einer benutzerdefinierten Funktion in Ihrem Programm mitteilen. Im Falle einer Deklaration ist kein Speicherplatz für eine Variable reserviert. Der Compiler weiß jedoch, wie viel Speicherplatz reserviert werden muss, wenn eine Variable dieses Typs erstellt wird.

Im Folgenden sind beispielsweise alle Erklärungen aufgeführt:

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

Definition bedeutet andererseits, dass zusätzlich zu all den Dingen, die die Deklaration tut, auch Speicherplatz im Speicher reserviert ist. Sie können sagen "DEFINITION = DECLARATION + SPACE RESERVATION". Dies sind Beispiele für die Definition:

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

siehe Antworten .


3
Auch dies ist falsch (obwohl viel näher als die anderen): struct foo {};ist eine Definition , keine Erklärung. Eine Erklärung von foowäre struct foo;. Aus diesem Grund weiß der Compiler nicht, wie viel Speicherplatz für fooObjekte reserviert werden soll.
sbi

1
@Marcin: sbi sagt, dass "Compiler weiß, wie viel Speicherplatz reserviert werden muss, wenn eine Variable dieses Typs erstellt wird" nicht immer wahr ist. struct foo;ist eine Deklaration, die dem Compiler jedoch nicht die Größe von foo mitteilt. Ich würde hinzufügen, dass dies struct _tagExample { int a; int b; };eine Definition ist. In diesem Zusammenhang ist es irreführend, von einer Erklärung zu sprechen. Natürlich ist es eine, da alle Definitionen Deklarationen sind, aber Sie scheinen zu behaupten, dass es keine Definition ist. Es ist eine Definition von _tagExample.
Steve Jessop

1
@Marcin Gil: Was bedeutet, dass das "Answers" -Wiki nicht immer korrekt ist. Ich muss hier für Fehlinformationen abstimmen.
David Thornley

1
Wir erfahren, dass das, was adatapost zitiert, wahr ist, aber die Frage nicht wirklich beantwortet (IMO). Was Marcin zitierte, ist falsch. Das Zitieren der Standards ist wahr und beantwortet die Frage, ist aber sehr schwer zu verstehen.
Steve Jessop

1
@ David Thornley - kein Problem :) Darum geht es auf dieser Seite. Wir wählen und überprüfen Informationen.
Marcin Gil

13

C ++ 11 Update

Da ich keine Antwort für C ++ 11 sehe, ist hier eine.

Eine Deklaration ist eine Definition, es sei denn, sie deklariert a / n:

  • undurchsichtige Aufzählung - enum X : int;
  • Vorlagenparameter - T intemplate<typename T> class MyArray;
  • Parameterdeklaration - x und y inint add(int x, int y);
  • Alias-Erklärung - using IntVector = std::vector<int>;
  • statische Assert-Deklaration - static_assert(sizeof(int) == 4, "Yikes!")
  • Attributdeklaration (implementierungsdefiniert)
  • leere Erklärung ;

Zusätzliche Klauseln, die von der obigen Liste von C ++ 03 geerbt wurden:

  • Funktionsdeklaration - fügen Sie inint add(int x, int y);
  • externer Bezeichner mit Deklaration oder Verknüpfungsbezeichner - extern int a;oderextern "C" { ... };
  • statisches Datenelement in einer Klasse - x inclass C { static int x; };
  • Klassen- / Strukturdeklaration - struct Point;
  • typedef Deklaration - typedef int Int;
  • mit Deklaration - using std::cout;
  • mit Direktive - using namespace NS;

Eine Template-Deklaration ist eine Deklaration. Eine Vorlagendeklaration ist auch eine Definition, wenn ihre Deklaration eine Funktion, eine Klasse oder ein statisches Datenelement definiert.

Beispiele aus dem Standard, der zwischen Deklaration und Definition unterscheidet, die ich zum Verständnis der Nuancen zwischen ihnen hilfreich fand:

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

6

Definition:

extern int a;      // Declaration 
int a;             // Definition
a = 10             // Initialization
int b = 10;        // Definition & Initialization

Die Definition ordnet die Variable einem Typ zu und weist Speicher zu, während die Deklaration nur den Typ angibt, aber keinen Speicher zuweist. Die Deklaration ist nützlicher, wenn Sie die Variable vor der Definition referenzieren möchten.

* Verwechseln Sie Definition nicht mit Initialisierung. Beide sind unterschiedlich, die Initialisierung gibt der Variablen einen Wert. Siehe das obige Beispiel.

Es folgen einige Beispiele für die Definition.

int a;
float b;
double c;

Jetzt Funktionsdeklaration:

int fun(int a,int b); 

Beachten Sie das Semikolon am Ende der Funktion, damit es nur eine Deklaration ist. Der Compiler weiß, dass diese Funktion irgendwo im Programm mit diesem Prototyp definiert wird . Wenn der Compiler nun eine Funktion erhält, rufen Sie so etwas auf

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

Der Compiler gibt einen Fehler aus, der besagt, dass es keine solche Funktion gibt. Weil es keinen Prototyp für diese Funktion gibt.

Beachten Sie den Unterschied zwischen zwei Programmen.

Programm 1

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

Dabei wird auch die Druckfunktion deklariert und definiert. Da kommt der Funktionsaufruf nach der Definition. Nun sehen Sie das nächste Programm.

Programm 2

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

Dies ist wichtig, da der Funktionsaufruf der Definition vorausgeht und der Compiler wissen muss, ob eine solche Funktion vorhanden ist. Also deklarieren wir die Funktion, die den Compiler informiert.

Definition:

Dieser Teil der Definition einer Funktion wird als Definition bezeichnet. Es sagt, was innerhalb der Funktion zu tun ist.

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

2
int a; //declaration; a=10; //definitionDas ist völlig falsch. Wenn es um Objekte mit automatischer Speicherdauer geht (Objekte, die innerhalb einer Funktionsdefinition deklariert wurden und nicht mit einem anderen Speicherklassenspezifizierer wie extern deklariert wurden), sind dies immer Definitionen.
Joey Pabalinas

Der Hauptunterschied besteht darin, dass in einer Erklärung angegeben wird, dass "irgendwo etwas existiert, das diese Merkmale (Typ usw.) aufweist", während in einer Definition angegeben wird, dass "ich etwas mit diesen Merkmalen deklariere und es hier auch als instanziiere" Gut." Da Sie solche Objekte mit automatischer Speicherdauer nicht weiter deklarieren können, handelt es sich immer um Definitionen.
Joey Pabalinas

Mit Ausnahme einiger seltsamer typedef Eckfälle, die ich immer vergesse, gilt als Faustregel, dass alle Definitionen Deklarationen sind. Denk darüber nach; Wenn Sie etwas instanziieren, müssen Sie dem Compiler auch mitteilen, dass das Ding existiert und welche Eigenschaften es hat.
Joey Pabalinas

Die Antwort wurde gemäß Ihrem ersten Kommentar aktualisiert. Ich stimme diesem Kommentar jedoch nicht zu. "Wenn Sie etwas instanziieren, müssen Sie dem Compiler auch mitteilen, dass dieses Ding existiert." Wir geben beim Instanziieren nicht immer den Typ von lhs an. Beispiel: a = 10. Wir spezifizieren keine "Merkmale" eines hier.
SRIDHARAN

4

Definition bedeutet tatsächliche Funktion geschrieben & Deklaration bedeutet einfache Deklarationsfunktion für z

void  myfunction(); //this is simple declaration

und

void myfunction()
{
 some statement;    
}

Dies ist die Definition der Funktionsfunktion


1
Und was ist mit Typen und Objekten?
sbi

4

Faustregel:

  • Eine Deklaration teilt dem Compiler mit, wie die Daten der Variablen im Speicher zu interpretieren sind. Dies wird für jeden Zugriff benötigt.

  • Eine Definition reserviert den Speicher, um die Variable vorhanden zu machen. Dies muss genau einmal vor dem ersten Zugriff geschehen.


2
Dies gilt nur für Objekte. Was ist mit Typen und Funktionen?
Leichtigkeitsrennen im Orbit

4

Um die Substantive zu verstehen, konzentrieren wir uns zuerst auf die Verben.

erklären - offiziell bekannt geben; proklamieren

definieren - um (jemanden oder etwas) klar und vollständig zu zeigen oder zu beschreiben

Wenn Sie also etwas deklarieren, sagen Sie einfach, was es ist .

// declaration
int sum(int, int);

Diese Zeile deklariert eine aufgerufene C-Funktion sum, die zwei Argumente vom Typ intakzeptiert und eine zurückgibt int. Sie können es jedoch noch nicht verwenden.

Wenn Sie angeben, wie es tatsächlich funktioniert , ist dies die Definition davon.

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

3

Um den Unterschied zwischen Deklaration und Definition zu verstehen, müssen wir den Assemblycode sehen:

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)

und das ist nur Definition:

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)

Wie Sie sehen können, ändert sich nichts.

Die Deklaration unterscheidet sich von der Definition, da sie Informationen enthält, die nur vom Compiler verwendet werden. Zum Beispiel weist uint8_t den Compiler an, die asm-Funktion movb zu verwenden.

Siehst du das:

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

Die Deklaration hat keine äquivalente Anweisung, da sie nicht ausgeführt werden muss.

Darüber hinaus teilt die Deklaration dem Compiler den Umfang der Variablen mit.

Wir können sagen, dass die Deklaration eine Information ist, die vom Compiler verwendet wird, um die korrekte Verwendung der Variablen festzustellen und wie lange ein Speicher zu einer bestimmten Variablen gehört.


2

Können Sie nicht allgemein sagen, dass eine Deklaration ein Bezeichner ist, in dem kein Speicher zugeordnet ist und eine Definition tatsächlich Speicher aus einem deklarierten Bezeichner zuweist?

Ein interessanter Gedanke: Eine Vorlage kann keinen Speicher zuweisen, bis die Klasse oder Funktion mit den Typinformationen verknüpft ist. Ist die Vorlagenkennung also eine Deklaration oder Definition? Es sollte eine Deklaration sein, da kein Speicher zugewiesen ist und Sie lediglich die Vorlagenklasse oder -funktion als Prototyp erstellen.


1
Ihre Definition ist an sich nicht falsch, aber "Speicherdefinition" erscheint bei Funktionsdefinitionen immer umständlich. In Bezug auf Vorlagen: Dies template<class T> struct foo;ist eine Vorlage Erklärung , und so ist dies template<class T> void f();. Vorlagendefinitionen spiegeln Klassen- / Funktionsdefinitionen auf dieselbe Weise wider. (Beachten Sie, dass ein Vorlagenname kein Typ- oder Funktionsname ist . An einer Stelle, an der Sie dies sehen können, können Sie eine Vorlage nicht als Typparameter einer anderen Vorlage übergeben. Wenn Sie Vorlagen anstelle von Typen übergeben möchten, benötigen Sie Vorlagenvorlagenparameter. )
sbi

Einverstanden, dass 'Speicherdefinition' umständlich ist, insbesondere in Bezug auf Funktionsdefinitionen. Die Deklaration ist int foo () und die Definition ist int foo () {// hier ein Code ..}. Normalerweise muss ich mein kleines Gehirn mit Konzepten umhüllen, die ich kenne - 'Speicher' ist eine Möglichkeit, es zumindest für mich direkt zu halten ... :)

2

Finden Sie ähnliche Antworten hier: Technische Interview Fragen in C .

Eine Deklaration gibt dem Programm einen Namen. Eine Definition enthält eine eindeutige Beschreibung einer Entität (z. B. Typ, Instanz und Funktion) innerhalb des Programms. Erklärungen können in einem bestimmten Bereich wiederholt werden, es wird ein Name in einem bestimmten Bereich eingeführt.

Eine Erklärung ist eine Definition, es sei denn:

  • Deklaration deklariert eine Funktion ohne Angabe ihres Körpers,
  • Die Deklaration enthält einen externen Bezeichner und keinen Initialisierer oder Funktionskörper.
  • Deklaration ist die Deklaration eines statischen Klassendatenelements ohne Klassendefinition.
  • Deklaration ist eine Klassennamendefinition.

Eine Definition ist eine Erklärung, es sei denn:

  • Definition definiert ein statisches Klassendatenelement,
  • Die Definition definiert eine Nicht-Inline-Elementfunktion.

1

Das wird wirklich kitschig klingen, aber es ist der beste Weg, die Begriffe in meinem Kopf klar zu halten:

Erklärung: Stellen Sie sich vor, wie Thomas Jefferson eine Rede hält ... "Ich erkläre hiermit, dass dieses FOO in diesem Quellencode existiert !!!"

Definition: Stellen Sie sich ein Wörterbuch vor, Sie suchen nach Foo und was es eigentlich bedeutet.


1

Eine Deklaration präsentiert dem Compiler einen Symbolnamen. Eine Definition ist eine Deklaration, die dem Symbol Platz zuweist.

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

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

1

Laut dem Handbuch der GNU C-Bibliothek ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )

In C liefert eine Deklaration lediglich die Information, dass eine Funktion oder Variable existiert, und gibt ihren Typ an. Für eine Funktionsdeklaration können auch Informationen zu den Typen ihrer Argumente bereitgestellt werden. Der Zweck von Deklarationen besteht darin, dem Compiler zu ermöglichen, Verweise auf die deklarierten Variablen und Funktionen korrekt zu verarbeiten. Eine Definition hingegen ordnet tatsächlich Speicher für eine Variable zu oder sagt, was eine Funktion tut.


0

Das Konzept der Deklaration und Definition stellt eine Gefahr dar, wenn Sie die externe Speicherklasse verwenden, da sich Ihre Definition an einem anderen Speicherort befindet und Sie die Variable in Ihrer lokalen Codedatei (Seite) deklarieren. Ein Unterschied zwischen C und C ++ besteht darin, dass in C Sie die Deklarationen normalerweise am Anfang einer Funktion oder Codepage erfolgen. In C ++ ist das nicht so. Sie können an einem Ort Ihrer Wahl deklarieren.


1
Dies verwechselt die Erklärung mit der Definition und ist eindeutig falsch.
sbi

0

Mein Lieblingsbeispiel ist "int Num = 5". Hier ist Ihre Variable 1. definiert als int 2. deklariert als Num und 3. instanziiert mit einem Wert von fünf. Wir

  • Definieren Sie den Typ eines Objekts, das integriert sein kann, oder eine Klasse oder Struktur.
  • Deklarieren Sie den Namen eines Objekts, sodass alles mit einem Namen deklariert wurde, das Variablen, Funktionen usw. enthält.

Mit einer Klasse oder Struktur können Sie ändern, wie Objekte definiert werden, wenn sie später verwendet werden. Zum Beispiel

  • Man kann eine heterogene Variable oder ein Array deklarieren, die nicht spezifisch definiert sind.
  • Mit einem Offset in C ++ können Sie ein Objekt definieren, das keinen deklarierten Namen hat.

Wenn wir das Programmieren lernen, werden diese beiden Begriffe oft verwechselt, weil wir oft beide gleichzeitig machen.


Ich verstehe nicht, warum so viele Leute die Antwort von sbi positiv bewertet haben. Ich habe die Antwort von bjhend positiv bewertet, die ziemlich gut, präzise, ​​genau und viel aktueller war als meine. Ich war traurig zu sehen, dass ich die erste Person seit 4 Jahren war, die dies tat.
Jason K.

0

Stufen einer ausführbaren Generation:

(1) Vorprozessor -> (2) Übersetzer / Compiler -> (3) Linker

In Stufe 2 (Übersetzer / Compiler) teilen Deklarationsanweisungen in unserem Code dem Compiler mit, dass diese Dinge wir in Zukunft verwenden werden, und Sie können die Definition später finden. Dies bedeutet:

Übersetzer stellen sicher, dass: was ist was? bedeutet Erklärung

und (3) Stufe (Linker) muss definiert werden, um die Dinge zu binden

Linker stellen sicher, dass: wo ist was? bedeutet Definition


0

Es gibt einige sehr klare Definitionen in K & R (2. Auflage); Es hilft, sie an einem Ort zu platzieren und als einen zu lesen:

"Definition" bezieht sich auf den Ort, an dem die Variable erstellt oder Speicher zugewiesen wird. "Deklaration" bezieht sich auf die Stellen, an denen die Art der Variablen angegeben ist, aber kein Speicher zugewiesen ist. [S. 33]

...

Es ist wichtig, zwischen der Deklaration einer externen Variablen und ihrer Definition zu unterscheiden . Eine Deklaration kündigt die Eigenschaften einer Variablen an (hauptsächlich ihren Typ). Eine Definition bewirkt auch, dass Speicher beiseite gelegt wird. Wenn die Zeilen

int sp;
double val[MAXVAL]

erscheinen außerhalb einer Funktion, definieren die externen Variablen spund valbewirken, dass der Speicher beiseite gelegt wird, und dienen auch als Deklaration für den Rest dieser Quelldatei.

Auf der anderen Seite die Linien

extern int sp;
extern double val[];

erklären , für den Rest der Quelldatei , die speine ist , intund dass valeine doubleAnordnung (deren Größe an anderer Stelle bestimmt wird), aber sie schaffen keine Variablen oder Reservelager für sie.

Es darf nur eine Definition einer externen Variablen unter allen Dateien geben, aus denen das Quellprogramm besteht. ... Arraygrößen müssen mit der Definition angegeben werden, sind jedoch mit einer externDeklaration optional . [S. 80-81]

...

In den Erklärungen wird die Interpretation angegeben, die jedem Bezeichner gegeben wird. Sie reservieren nicht unbedingt den mit der Kennung verknüpften Speicher. Erklärungen, die Speicher reservieren, werden als Definitionen bezeichnet . [S. 210]


-1

Deklaration bedeutet, einer Variablen Namen und Typ zu geben (im Falle einer Variablendeklaration), z.

int i;

oder geben Sie einer Funktion ohne Body Namen, Rückgabetyp und Parametertyp (im Falle einer Funktionsdeklaration), z.

int max(int, int);

wohingegen Definition bedeutet, einer Variablen einen Wert zuzuweisen (im Fall einer Variablendefinition), z.

i = 20;

oder Bereitstellen / Hinzufügen eines Körpers (Funktionalität) zu einer Funktion wird als Funktionsdefinition bezeichnet, z.

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

Viele Zeitdeklarationen und Definitionen können zusammen durchgeführt werden als:

int i=20;

und:

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

In den obigen Fällen definieren und deklarieren wir die Variablen iund function max().


das tatsächliche Mittel der Definition, wenn einer Variablen / Funktion Wert / Körper zugewiesen werden soll, während Deklarationsmittel einer Variablen / Funktion Namen und Typ geben
Puneet Purohit

Sie können etwas definieren, ohne ihm einen Wert zuzuweisen.
Leichtigkeitsrennen im Orbit

1
Einfach so:int x;
Leichtigkeitsrennen im Orbit

Es ist eine Deklaration der Variablen x, nicht ihre Definition
Puneet Purohit

2
Nein, es ist beides. Sie verwechseln Definition mit Initialisierung.
Leichtigkeitsrennen im Orbit
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.