Um die Frage zu beantworten, die Sie in mehreren Kommentaren gepostet haben (die Sie meines Erachtens in Ihrem Beitrag bearbeiten sollten):
Was ich nicht verstehe, ist, wie der Computer wissen kann, wenn er den Wert einer Variablen ausliest und Adressen wie 10001, wenn es sich um ein int oder ein char handelt. Stellen Sie sich vor, ich klicke auf ein Programm namens anyprog.exe. Der Code wird sofort ausgeführt. Enthält diese exe-Datei Informationen darüber, ob die Variablen als in oder char gespeichert sind?
Fügen wir also Code hinzu. Angenommen, Sie schreiben:
int x = 4;
Und nehmen wir an, dass es im RAM gespeichert wird:
0x00010004: 0x00000004
Der erste Teil ist die Adresse, der zweite Teil ist der Wert. Wenn Ihr Programm (das als Maschinencode ausgeführt wird) ausgeführt wird, 0x00010004
wird nur der Wert angezeigt 0x000000004
. Der Typ dieser Daten ist nicht bekannt, und es ist nicht bekannt, wie sie verwendet werden sollen.
Wie findet Ihr Programm das Richtige heraus? Betrachten Sie diesen Code:
int x = 4;
x = x + 5;
Wir haben hier ein Lesen und ein Schreiben. Wenn Ihr Programm x
aus dem Speicher liest , wird es 0x00000004
dort gefunden. Und Ihr Programm kann es ergänzen 0x00000005
. Und der Grund, warum Ihr Programm "weiß", dass dies eine gültige Operation ist, liegt darin, dass der Compiler durch Typensicherheit sicherstellt, dass die Operation gültig ist. Ihr Compiler hat bereits überprüft, ob Sie 4
und 5
zusammen hinzufügen können . Wenn Ihr Binärcode (die Exe) ausgeführt wird, muss er diese Überprüfung nicht durchführen. Es führt jeden Schritt einfach blind aus, vorausgesetzt, alles ist in Ordnung (schlechte Dinge passieren, wenn sie tatsächlich sind, nicht in Ordnung).
So kann man es sich auch vorstellen. Ich gebe Ihnen diese Informationen:
0x00000004: 0x12345678
Gleiches Format wie zuvor - Adresse links, Wert rechts. Welcher Typ ist der Wert? Zu diesem Zeitpunkt kennen Sie genau so viele Informationen zu diesem Wert wie Ihr Computer, wenn er Code ausführt. Wenn Sie 12743 zu diesem Wert hinzufügen sollten, könnten Sie es tun. Sie haben keine Ahnung, welche Auswirkungen diese Operation auf das gesamte System haben wird, aber das Hinzufügen von zwei Zahlen ist etwas, in dem Sie wirklich gut sind, also können Sie es tun. Macht das den Wert an int
? Nicht unbedingt - Sie sehen nur zwei 32-Bit-Werte und den Additionsoperator.
Vielleicht liegt ein Teil der Verwirrung dann darin, die Daten wieder herauszuholen. Wenn wir haben:
char A = 'a';
Woher weiß der Computer, dass er a
in der Konsole angezeigt wird? Nun, dazu gibt es viele Schritte. Das erste ist, zu A
s Speicherort im Speicher zu gehen und ihn zu lesen:
0x00000004: 0x00000061
Der a
hexadezimale Wert für in ASCII ist 0x61, so dass der obige Wert möglicherweise im Speicher angezeigt wird. Unser Maschinencode kennt jetzt also den ganzzahligen Wert. Woher weiß es, dass der ganzzahlige Wert in ein Zeichen umgewandelt werden muss, um ihn anzuzeigen? Einfach ausgedrückt, der Compiler hat dafür gesorgt, dass alle erforderlichen Schritte für diesen Übergang ausgeführt wurden. Ihr Computer selbst (oder das Programm / die Exe-Datei) hat jedoch keine Ahnung, um welche Art von Daten es sich handelt. Das 32-Bit - Wert könnte alles sein - int
, die char
Hälfte ein double
, einen Zeiger, einen Teil einer Anordnung, die Teil eines string
, einen Teil eines Befehls usw.
Hier ist eine kurze Interaktion, die Ihr Programm (exe) möglicherweise mit dem Computer / Betriebssystem hat.
Programm: Ich möchte anfangen. Ich brauche 20 MB Speicher.
Betriebssystem: Findet 20 MB freien Speicher, der nicht verwendet wird, und übergibt sie
(Die wichtige Anmerkung ist , dass diese zurückkehren konnten alle 20 kostenlosen MB Speicher, sie haben nicht einmal zusammenhängend sein müssen. Zu diesem Zeitpunkt kann das Programm nun im Speicher arbeiten hat , ohne auf die OS im Gespräch)
Programm: Ich gehe davon aus, dass der erste Punkt im Speicher eine 32-Bit-Ganzzahlvariable ist x
.
(Der Compiler stellt sicher, dass Zugriffe auf andere Variablen diese Stelle im Speicher niemals berühren. Es gibt nichts auf dem System, was besagt, dass das erste Byte eine Variable ist x
, oder dass diese Variable x
eine Ganzzahl ist. Eine Analogie: Sie haben eine Tasche. Sie sagen dies den Leuten Sie werden nur gelbe Kugeln in diese Tasche legen. Wenn jemand später etwas aus der Tasche zieht, dann wäre es schockierend, wenn er etwas Blaues oder einen Würfel herausziehen würde - etwas ist schrecklich schief gelaufen. Gleiches gilt für Computer: Ihre Das Programm geht jetzt davon aus, dass der erste Speicherplatz die Variable x und eine Ganzzahl ist. Wenn jemals etwas anderes über dieses Byte des Speichers geschrieben wurde oder angenommen wird, dass es sich um etwas anderes handelt, ist etwas Schreckliches passiert nicht passieren)
Programm: Ich werde jetzt 2
auf die ersten vier Bytes schreiben , bei denen ich davon ausgehe, dass x
es sich um handelt.
Programm: Ich möchte 5 hinzufügen x
.
Liest den Wert von X in ein temporäres Register
Fügt dem temporären Register 5 hinzu
Speichert den Wert des temporären Registers zurück in das erste Byte, das immer noch angenommen wird x
.
Programm: Ich gehe davon aus, dass das nächste verfügbare Byte die Variable char ist y
.
Programm: Ich werde a
in Variable schreiben y
.
Eine Bibliothek wird verwendet, um den Bytewert für zu finden a
Das Byte wird an die Adresse geschrieben, von der das Programm ausgeht y
.
Programm: Ich möchte den Inhalt von anzeigen y
Liest den Wert im zweiten Speicherpunkt
Verwendet eine Bibliothek, um aus dem Byte ein Zeichen zu konvertieren
Verwendet Grafikbibliotheken zum Ändern des Konsolenbildschirms (Einstellen der Pixel von Schwarz auf Weiß, Scrollen um eine Zeile usw.)
(Und es geht weiter von hier)
Woran werden Sie wahrscheinlich hängen bleiben x
? Was passiert, wenn der erste Punkt in der Erinnerung nicht mehr vorhanden ist ? oder ist die zweite nicht mehr y
? Was passiert, wenn jemand x
als char
oder y
als Zeiger liest ? Kurz gesagt, schlimme Dinge passieren. Einige dieser Dinge haben ein genau definiertes Verhalten, andere undefiniertes. Undefiniertes Verhalten ist genau das - alles kann passieren, von nichts bis zum Absturz des Programms oder des Betriebssystems. Sogar genau definiertes Verhalten kann böswillig sein. Wenn ich x
zu einem Zeiger auf mein Programm wechseln und Ihr Programm dazu bringen kann, ihn als Zeiger zu verwenden, kann ich Ihr Programm dazu bringen, mein Programm auszuführen - genau das tun Hacker. Der Compiler ist da, um sicherzustellen, dass wir nicht int x
alsstring
und solche Dinge. Der Maschinencode selbst kennt keine Typen und tut nur das, was in den Anweisungen angegeben ist. Es gibt auch eine große Menge an Informationen, die zur Laufzeit entdeckt werden: Welche Bytes an Speicher darf das Programm verwenden? Beginnt x
am ersten Byte oder am 12.?
Aber Sie können sich vorstellen, wie schrecklich es wäre, Programme wie dieses zu schreiben (und das können Sie auch in der Assemblersprache). Sie beginnen mit der 'Deklaration' Ihrer Variablen - Sie sagen sich, dass Byte 1 x
Byte 2 ist y
, und wenn Sie jede Codezeile schreiben, Register laden und speichern, müssen Sie sich (als Mensch) merken, welches ist x
und welches Eines ist y
, weil das System keine Ahnung hat. Und Sie (als Mensch) müssen sich merken, welche Typen x
und welche y
sind, denn auch hier hat das System keine Ahnung.