Die Bedeutung von beiden entgeht mir.
Die Bedeutung von beiden entgeht mir.
Antworten:
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.
extern int i
ist eine Deklaration, da sie nur einführt / spezifiziert i
. Sie können so viele extern int i
in jeder Kompilierungseinheit haben, wie Sie möchten. int i
ist jedoch eine Definition. Es bezeichnet den Platz für die Ganzzahl in dieser Übersetzungseinheit und empfiehlt dem Linker, alle Verweise auf i
diese Entität zu verknüpfen . Wenn Sie mehr oder weniger als genau eine dieser Definitionen haben, wird sich der Linker beschweren.
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.
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.
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 extern
Schlü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 typedef
oder using
Aussage.
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.
struct x {static int b = 3; };
?
b
auch deklariert const
. Siehe stackoverflow.com/a/3536513/1858225 und daniweb.com/software-development/cpp/threads/140739/… .
Erklärung: "Irgendwo gibt es ein Foo."
Definition: "... und hier ist es!"
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 T
handelt:
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>::member
Sie 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.
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.
class foo {};
ist eine Klasse Definition , ist es nicht?
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:
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 ++.
typedef
Würde das nicht bedeuten, dass es in C ++ wiederholt werden könnte, aber nicht in C99?
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 .
struct foo {};
ist eine Definition , keine Erklärung. Eine Erklärung von foo
wäre struct foo;
. Aus diesem Grund weiß der Compiler nicht, wie viel Speicherplatz für foo
Objekte reserviert werden soll.
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.
Da ich keine Antwort für C ++ 11 sehe, ist hier eine.
Eine Deklaration ist eine Definition, es sei denn, sie deklariert a / n:
enum X : int;
template<typename T> class MyArray;
int add(int x, int y);
using IntVector = std::vector<int>;
static_assert(sizeof(int) == 4, "Yikes!")
;
Zusätzliche Klauseln, die von der obigen Liste von C ++ 03 geerbt wurden:
int add(int x, int y);
extern int a;
oderextern "C" { ... };
class C { static int x; };
struct Point;
typedef int Int;
using std::cout;
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
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);
}
int a; //declaration; a=10; //definition
Das 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.
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
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.
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 int
akzeptiert 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;
}
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.
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.
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. )
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:
Eine Definition ist eine Erklärung, es sei denn:
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.
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.
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.
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
Mit einer Klasse oder Struktur können Sie ändern, wie Objekte definiert werden, wenn sie später verwendet werden. Zum Beispiel
Wenn wir das Programmieren lernen, werden diese beiden Begriffe oft verwechselt, weil wir oft beide gleichzeitig machen.
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
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
sp
undval
bewirken, 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
sp
eine ist ,int
und dassval
einedouble
Anordnung (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
extern
Deklaration 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]
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 i
und function max()
.
int x;