Wenn eine Variable in C ++ / C deklariert wird

7

Wenn ich eine Variable deklariere, zB:

%Vor%

Was genau ist x ? eine Adresse im Speicher ist normalerweise hexadezimal Auch wenn ich X rufe.

%Vor%

Woher weiß der Compiler, wo x ist? x ist keine Adresse.

Das war meine erste Frage.

Zweitens:
Nehmen wir an, ich habe ein Objekt:
Person p;
p hat 2 Datenmember:

%Vor%

Was genau ist p , und warum muss ich zu p gehen, dann die Variable?

%Vor%     
user1725859 12.10.2012, 14:06
quelle

11 Antworten

5

Im Fall int x = 6 ist x nur ein Name, der Ihnen hilft, den Code zu schreiben, und der Compiler kompiliert ihn. Es ist im Grunde ein Alias ​​für einen Platz im Speicher, so dass es später leichter ist, über x = 2 darauf zuzugreifen - das sagt Ihnen und dem Compiler, dass Sie den Wert 2 an derselben Stelle schreiben wollen.

Wie zuvor, aber es braucht mehr Platz ( sizeof(Person) um genau zu sein). p->type1 ist nur gültig, wenn p ein Zeiger auf ein Person ist (oder wenn Sie den -> -Operator überladen haben, aber das ist nicht der Fall), p.type1 ist die für ein Objekt verwendete Syntax, um das zu spezifizieren Teil des es Sie zugreifen möchten.

    
Luchian Grigore 12.10.2012 14:10
quelle
5
%Vor%

Hier ist x ein Bezeichner, d. h. name given to memory area , wo der Wert 6 gespeichert ist.
x ist ein einfacher Name, um nur den Speicherbereich zu identifizieren, in dem der Wert 6 gespeichert ist.
Wenn Sie eine Variable deklarieren, speichert dieser Zeit-Compiler Ihren Variablennamen in der Bezeichner-Tabelle.

Für person p wird hier noch einmal p dem Speicherbereich zugewiesen, der zwei Datenelemente type1 & amp; type2

Für den Zugriff auf den Wert von type1 & amp; type2 , zuerst müssen Sie den Speicherbereich finden, wo sie gespeichert sind. Deshalb müssen Sie zuerst auf den Speicherbereich p & amp; Dann können Sie auf type1 * type2

zugreifen     
Ravindra Bagale 12.10.2012 14:08
quelle
4

x ist ein Lvalue, was "Lokatorwert" bedeutet. Es heißt so, weil der Compiler von x weiß, wo er sich befindet. Also ist x gewissermaßen eine Adresse oder etwas, das es ermöglicht, eine Adresse abzuleiten.

Das Ding wird nur beim Lesen zu einem Wert

%Vor%

In diesem Fall nimmt der Compiler x , liest den Wert an seinem Ort und fortan steht in dieser Initialisierung x für seinen Wert. Leider ist dieses "Wertlesen" ein impliziter Prozess. Ob also der Text x ein Wert oder ein Lvalue ist, hängt davon ab, wo er erscheint.

    
Johannes Schaub - litb 12.10.2012 14:12
quelle
3
%Vor%

Was genau ist X?

x ist eine Variable, die als Name definiert werden kann, der einem Speicherort im Speicher zugewiesen wird.

Woher weiß der Compiler, wo x ist?

Es gibt eine so genannte Symboltabelle , die der Compiler intern verwendet, um Variablennamen den tatsächlichen Speicherpositionen zuzuordnen.

    
Raj 12.10.2012 14:21
quelle
1

x ist ein Variablenbezeichner. Eine Variable unterscheidet sich von einer Adresse dadurch, dass sie eine Größe hat und nicht null sein kann. Die Adresse von x kann mit &x erhalten werden. Betrachten Sie diesen Code:

%Vor%

Nun, obwohl du nur den Wert von x geändert hast, erhältst du auch 6, wenn du den Wert von *p (genannt Dereferenzieren des Zeigers) bekommst. p ist auch eine Variable, aber es hat den Typ 'Zeiger auf int' anstatt 'int', was der Typ x hat.

    
benwad 12.10.2012 14:12
quelle
1

Dass es eine Variable ist, ist alles, was man mit Vertrauen sagen kann.

Es hat möglicherweise keine Speicheradresse, wenn das Optimierungsprogramm es in ein Register gestellt hat. Wenn es eine Speicheradresse hat, könnte es eine feste absolute Adresse (für Globals und Statik in nicht verschiebbarem Code), eine Adresse relativ zu einem anderen Objekt (für nicht statische Member) oder eine Adresse relativ zum Stack erhalten Rahmen (für automatische lokale Variablen).

Es ist möglicherweise nicht einmal ein Speicherort, wenn der Compiler feststellt, dass er den Wert immer vorhersagen und diesen Wert bei jeder Verwendung ersetzen kann.

Wenn Sie den Operator & address-of für die Variable verwenden, muss der Compiler ihm einen Speicherort geben.

    
Ben Voigt 12.10.2012 14:33
quelle
1

x ist eine Variable. Oder genauer der Name oder die Bezeichnung des Ortes, an dem die Information (Daten) gespeichert ist, auf die sich diese Variable bezieht. Sie benötigen Labels, um zwischen verschiedenen Variablen zu unterscheiden. Es ist nur für Sie (der Programmierer) da, um Ihnen zu helfen.

p ist wieder eine Variable, aber vom Typ Person . Und Person ist eine Datenstruktur - sie enthält Daten, auf die Sie über die Struktur zugreifen. Und p ist ein Objekt (z. B. Instanziierung der Struktur) dieses Typs. Sie können zwei Objekte des gleichen Typs haben

%Vor%

Um zu wissen, auf welche Daten / Mitglieder Sie zugreifen möchten, verwenden Sie p.data someone.data

Warum p->data ?

p->data Syntax entspricht (*p).data

Das erklärt, was Zeiger ist. Wie ich schon sagte Variable ist ein Ort, wo Sie einige Informationen (Daten) speichern. Einfach gesagt, der Zeiger ist eine Variable, die eine Speicheradresse speichert. Mit anderen Worten, es zeigt auf einen anderen Wert, der irgendwo im Speicher gespeichert ist

Zum Beispiel:

%Vor%

*p in (*p).data heißt Dereferenzieren eines Zeigers (Zugreifen auf den Wert, auf den der Zeiger zeigt)

Für weitere Informationen ist es eine gute Idee, Google-Zeiger oder noch besser eine Buch zum Lesen

    
tozka 12.10.2012 14:18
quelle
1

Das Wort ist nicht die Sache.

Alle x und p , und für diese Angelegenheit p.type1 sind Namen oder Bezeichner. Also, ich denke, du fragst wirklich nach was sie identifizieren . Die Antwort ist, dass sie etwas identifizieren, das sich wie verhält, als ob es bestimmte Anforderungen der Sprachspezifikation erfüllt. Was diese identifizierte Sache tatsächlich ist, hängt von Ihrer Plattform, Ihrem Compiler, vielleicht von welchen Optimierungen, usw. ab usw.

Nehmen wir also die Aussage

%Vor%

Sie sagen, dass x jetzt (in diesem Bereich und möglicherweise verschachtelten Bereichen) auf ein int (was auch immer das ist) verweist und ihm den anfänglichen ganzzahligen Literalwert 6 gibt.

Also, was ist ein int ? Es ist eine Sache , die einen einzelnen (positiven oder negativen) ganzzahligen Wert im Bereich [std::numeric_limits<int>::min(),std::numeric_limits<int>::max()] enthalten kann. Seine genaue Größe ist architekturabhängig, aber mindestens so groß wie ein char und nicht größer als ein long (IIRC).

Wahrscheinliche Kandidaten für das, was diese Sache sein könnte:

  • genügend Speicher, um alles zu halten, was int auf Ihrer Plattform ist, verbunden mit einem Linkersymbol (möglicherweise zur Laufzeit verschoben), wenn es sich um eine globale Deklaration handelt, so dass der gesamte Code auf x denselben Speicherort verwendet li>
  • genügend Speicher bei einem festen Offset vom Stack- (oder Stack-Frame-) Zeigerregister, wenn es sich um eine lokale Funktion-Scope-Variable handelt: Der Compiler ist verantwortlich für das Verfolgen der Variablen, die er hier in jeder Funktion einfügen wird, und erinnert sich an den Offset ist jeder Kennung zugeordnet. Dies ist ein allgemeiner (nicht optimierter) Standardfall
  • ein Register, das groß genug ist, um int zu speichern: Wenn du nie die Adresse von x nimmst, kann es sein ganzes Leben in einem Register verbringen, aber wenn du entweder die Adresse nimmst oder der Compiler läuft Aus den Registern für alle Ihre Variablen (oder müssen sie über einen Funktionsaufruf hinweg gespeichert werden), kann x in ein Register geladen werden, wenn Sie damit arbeiten, und zurück zum Stack verschüttet werden. Auch hier ist es an dem Compiler, sich an zu erinnern, wenn x momentan ein Register ist (und welches) und wenn es ein Speicherort ist

Wie Sie sehen, kann das "Ding" x wirklich viele Dinge an verschiedenen Stellen während der Ausführung Ihres Programms ausmachen.

Es sei denn, Sie optimieren etwas oder legen Ihren Speicher sorgfältig aus. Eine nützlichere Frage ist was sind die Eigenschaften von x ?

Der Sinn des Standards (oder einer anderen Sprachspezifikation) besteht darin, einige nützliche Garantien über Typen, Variablen und Verhaltensweisen zu geben und dann den Compiler entscheiden zu lassen, wie diese Garantien erreicht werden.

    
Useless 12.10.2012 16:02
quelle
1

Nehmen wir einen Schritt zurück ... es ist wichtig zu verstehen, dass alle Programmiersprachen (abgesehen von der Assemblersprache) eine Abstraktion eines Problems in Begriffen beschreiben, die für Programmierer leicht zu denken sind. Es ist die Aufgabe des Compilers, diese abstrakte Beschreibung zu lesen und eine Beschreibung auf niedrigerer Ebene zu generieren, die direkt der Hardware entspricht.

Wenn Sie schreiben:

%Vor%

Sie sagen dem Compiler, dass Sie eine Integer-Variable verwenden möchten, dass Sie die Variable x aufrufen wollen und dass die Variable den Wert 6 haben soll.

Einer der Jobs des Compilers ist zu entscheiden, wie diese Variable gespeichert wird. Die C ++ - Sprache beschreibt verschiedene Arten von Variablenbereichen, die dem Compiler helfen zu entscheiden, welche Art von Speicher geeignet ist.

  • Eine lokale Variable (innerhalb einer Funktion deklariert) wird normalerweise im Speicher des Stacks gespeichert, aber ein kleiner Wert (wie eine ganze Zahl) könnte in einem Register gespeichert werden.

  • Eine globale oder statische Variable wird im Speicher gespeichert.

Der Compiler merkt sich, wo er den Wert gespeichert hat, so dass er ihn wiederfinden kann - für ein lokales Varable, das der Registername oder eine Adresse relativ zum oberen Teil des Stacks sein wird; Für eine globale oder statische Adresse wird es eine Adresse sein, die sich auf den Anfang aller Programmdaten bezieht.

Die tatsächliche Adresse im Speicher ist nicht bekannt, bis das Programm kompiliert, verknüpft und in den Speicher geladen wurde (weil das OS das Programm nicht immer an der gleichen Adresse lädt) - wichtig ist, dass der Compiler es weiß wo die Variable sein wird und dass sie Code generieren kann, um darauf zuzugreifen.

Wenn, wie in Ihrer zweiten Frage, der Typ der Variablen eine Datenstruktur ist, wählt der Compiler genau auf die gleiche Weise, wo er in den Speicher eingefügt werden soll. Wenn Ihr Programm auf einen Member dieser Struktur zugreift, kann der Compiler die Adresse des Members ermitteln, da er die Adresse der Struktur und auch den Offset des Members innerhalb der Struktur kennt.

Also, im Falle Ihres person p Beispiels, wenn das Programm auf p1.type2 verweist, nimmt der Compiler die Adresse von p und fügt den Offset von type2 hinzu (was wahrscheinlich 4 ist, weil der erste Ein Teil Ihrer struct person wird mit type1 aufgegriffen, was eine Ganzzahl ist, die 4 Bytes beträgt (bei den meisten 32-Bit-Architekturen)).

Sie müssen sowohl p als auch type2 angeben, da Sie möglicherweise eine andere Person haben (zB q ) und dem Compiler mitgeteilt werden muss, welche Person Sie manipulieren wollen. p.type2 ist nicht dieselbe Variable wie q.type2 und hat eine andere Adresse.

    
dajames 12.10.2012 16:17
quelle
0

Lesen Sie über Stack und Heaps.

x wird mit einer eindeutigen Adresse auf den Stapel geschoben. Aber Sie müssen nur x anrufen.

aber versuchen Sie cout & lt; & lt; & amp; x;

Das ist die wirkliche Adresse

    
Pavenhimself 12.10.2012 14:11
quelle
-1

Wenn Sie Ihre Variable deklarieren, ordnet Ihr Compiler sie mit einer Variablenattributtabelle zu. Und diese Tabelle enthält Adresse und Größe, Typ usw. Der Compiler holt bei Bedarf Dinge aus dieser Tabelle.

    
Avaneesh Kumar 12.10.2012 14:14
quelle

Tags und Links