Wie unterscheidet ein Computer "\ 0" (Nullzeichen) von "unsigned int = 0"?

29

Wenn Sie in einer bestimmten Situation eine Reihe von Zeichen haben (die natürlich mit dem Null-Zeichen enden) und unmittelbar danach an der nächsten Stelle im Speicher 0als vorzeichenloses int speichern möchten , wie unterscheidet der Computer diese zwei?

Angelixus
quelle
18
Sie fragen nach typischen Computern, auf denen die Antworten völlig richtig sind. Es gab jedoch einige Architekturen, die zur Unterscheidung der Datentypen den getaggten Speicher verwendeten.
Grawity
12
Auf die gleiche Weise kann der Computer einen 4-Byte-Gleitkommawert nicht von einer 4-Byte-Ganzzahl unterscheiden (die eine ganz andere Zahl darstellt).
Hagen von Eitzen
6
Während das Beenden einer Zeichenfolge mit 0x00 üblich ist, gibt es Sprachen, die Zeichenfolgen mit Längenpräfix verwenden. Das erste oder die zwei Bytes enthalten die Anzahl der Bytes in der Zeichenfolge. Auf diese Weise wird am Ende kein 0x00 benötigt. Ich erinnere mich an Pascal und BASIC, die das gemacht haben. Vielleicht auch COBOL.
leuchtet
@lit formatiert auch Header in vielen Kommunikationsprotokollen. "Hallo, ich bin diese Art von Nachricht und ich bin so viele Bytes lang". Da Sie häufig komplexe Datentypen speichern müssen, ist das Parsen der Nullterminierung viel schwieriger.
Kathreadler
1
@lit: Die meisten Varianten von Pascal und BASIC ja, und PL / I und Ada - und in Java seit String - Sharing in 7u6 fallen gelassen wurde verwendet effektiv das Array Längenpräfix - aber COBOL nur sort-of: Sie können lesen von Daten pic X occurs m to n depending on v( und die Zählung kann überall sein, nicht nur unmittelbar davor, aber das Speichern ist komplizierter.
Dave_thompson_085

Antworten:

86

Das tut es nicht.

Der Zeichenkettenabschluss ist ein Byte, das alle 0 Bits enthält.

Das vorzeichenlose int besteht aus zwei oder vier Bytes (abhängig von Ihrer Umgebung), die jeweils alle 0 Bits enthalten.

Die beiden Elemente werden an verschiedenen Adressen gespeichert. Ihr kompilierter Code führt Operationen aus, die für Zeichenfolgen an der ersten Position und für nicht vorzeichenbehaftete Binärzahlen an der zweiten Position geeignet sind. (Es sei denn, Sie haben einen Fehler in Ihrem Code oder einen gefährlich cleveren Code!)

Aber alle diese Bytes sehen für die CPU gleich aus. Daten im Speicher (in den meisten derzeit üblichen Befehlssatzarchitekturen) sind keinem Typ zugeordnet. Das ist eine Abstraktion, die nur im Quellcode existiert und nur dem Compiler etwas bedeutet.

Bearbeiten hinzugefügt: Als Beispiel: Es ist durchaus möglich, auch häufig, Arithmetik mit den Bytes durchzuführen, aus denen eine Zeichenfolge besteht. Wenn Sie eine Zeichenfolge mit 8-Bit-ASCII-Zeichen haben, können Sie die Buchstaben in der Zeichenfolge zwischen Groß- und Kleinschreibung umwandeln, indem Sie 32 (dezimal) addieren oder subtrahieren. Wenn Sie in einen anderen Zeichencode übersetzen, können Sie deren Werte als Indizes in einem Array verwenden, dessen Elemente die entsprechende Bitcodierung im anderen Code bereitstellen.

Für die CPU sind die Zeichen wirklich sehr kurze ganze Zahlen. (jeweils acht Bits anstelle von 16, 32 oder 64.) Für uns Menschen sind ihre Werte zufällig mit lesbaren Zeichen verknüpft, aber die CPU hat keine Ahnung davon. Es weiß auch nichts über die "C" -Konvention von "null Byte endet eine Zeichenkette" (und wie viele in anderen Antworten und Kommentaren angemerkt haben, gibt es Programmierumgebungen, in denen diese Konvention überhaupt nicht verwendet wird). .

Natürlich gibt es in x86 / x64 einige Anweisungen, die häufig für Zeichenfolgen verwendet werden - beispielsweise das REP-Präfix -, aber Sie können sie auch für ein Array von Ganzzahlen verwenden, wenn sie das gewünschte Ergebnis erzielen.

Jamie Hanrahan
quelle
14
Deshalb müssen Entwickler mit Strings vorsichtig sein. Wenn Sie beispielsweise 100 aufeinanderfolgende Bytes haben, können Sie maximal 99 1-Byte-Zeichen plus das Abschlusszeichen im letzten Byte einfügen. Wenn Sie dort eine 100-Byte-Zeichenfolge eingeben, kann das Programm nicht feststellen, dass die Zeichenfolge dort endet, und liest so lange aufeinanderfolgende Bytes, bis ein zufälliges Null-Byte vorliegt. Wenn die Zeichenfolge länger als 100 Byte ist, werden einige benachbarte Daten überschrieben. Programmiersprachen auf hoher Ebene (Java, C #, JS usw.) kümmern sich selbst darum, aber in langsamen Umgebungen wie C, C ++ und Assembly ist es die Verantwortung des Entwicklers.
Gronostaj
18
@gronostaj Ihr Kommentar ist etwas verwirrend: Anders als in C kümmern sich auch C ++ - Strings automatisch darum. C ++ wird im Allgemeinen auch nicht als einfache Sprache klassifiziert (und selbst C ist dies manchmal nicht).
Konrad Rudolph
5
Es gibt (alte) CPU-Architekturen mit Typmarkierungen für Datenwerte. Wenn Sie also eine Ganzzahl als Zeiger dereferenzieren, tritt eine Ausnahme auf.
Simon Richter
8
@ Jamie Hanrahan Der IA64-Prozessor hat ein Bit namens NaT (oder "Not a Thing"), das eine Ausnahme auslösen kann, wenn ein Wert gesetzt ist.
ErikF
4
@KonradRudolph "automatisch" bedeutet nicht "kinderleicht", schon gar nicht in C ++
Rackandboneman
5

Kurz gesagt, es gibt keinen Unterschied (außer dass ein int 2 oder 4 Bytes breit ist und ein char nur 1).

Die Sache ist, dass alle modernen Bibliotheken entweder die Null-Terminator-Technik verwenden oder die Länge eines Strings speichern. In beiden Fällen weiß das Programm / der Computer, dass es das Ende einer Zeichenfolge erreicht hat, wenn es entweder ein Nullzeichen liest oder so viele Zeichen gelesen hat, wie die Größe es vorgibt.

Probleme mit diesem Start, wenn das Null-Abschlusszeichen fehlt oder die Länge falsch ist, da das Programm beginnt, aus dem Speicher zu lesen, den es nicht sollte.

BrainStone
quelle
3
Oh, es gibt einen Unterschied in Kurzform - eigentlich ist Kurzform dafür berüchtigt, ein sehr maschinenabhängiger Datentyp zu sein :)
rackandboneman
2

Es gibt keinen Unterschied. Maschinencode (Assembler) hat keine Variablentypen, stattdessen wird der Typ der Daten durch die Anweisung bestimmt.

Ein besseres Beispiel wäre intund floatwenn Sie 4 Bytes im Speicher haben, gibt es keine Informationen darüber, ob es ein intoder ein float(oder etwas ganz anderes) ist, es gibt jedoch 2 verschiedene Anweisungen für die Ganzzahladdition und die Gleitkommazahladdition, wenn also die Ganzzahladdition Befehl wird für die Daten verwendet, dann ist es eine Ganzzahl und umgekehrt.

Gleiches gilt für Zeichenfolgen. Wenn Sie Code haben, der beispielsweise eine Adresse ansieht und Bytes zählt, bis ein \0Byte erreicht ist, können Sie sich dies als Länge einer Funktionsberechnungszeichenfolge vorstellen.

Natürlich wäre das Programmieren so ein Wahnsinn, deshalb haben wir höhere Sprachen, die sich zu Maschinencode kompilieren lassen, und fast keine Programme in Assembler direkt.

kajacx
quelle
2

Die wissenschaftliche Einzelwortantwort wäre: Metadaten.

Die Metadaten teilen dem Computer mit, ob es sich bei einigen Daten an einem bestimmten Ort um ein Int, eine Zeichenfolge, einen Programmcode oder was auch immer handelt. Diese Metadaten können Teil des Programmcodes sein (wie von Jamie Hanrahan erwähnt) oder sie können explizit irgendwo gespeichert werden.

Moderne CPUs können häufig zwischen Speicherbereichen, die Programmcode zugeordnet sind, und Datenbereichen unterscheiden (z. B. das NX-Bit https://en.wikipedia.org/wiki/NX_bit ). Manche exotische Hardware kann auch zwischen Zeichenfolgen und Zahlen unterscheiden, ja. Der übliche Fall ist jedoch, dass sich die Software um dieses Problem kümmert, entweder durch implizite Metadaten (im Code) oder explizite Metadaten (objektorientierte VMs speichern die Metadaten (Typ- / Klasseninformationen) häufig als Teil der Daten (Objekt)). .

Ein Vorteil der Nichtunterscheidung zwischen verschiedenen Datentypen besteht darin, dass einige Vorgänge sehr einfach werden. Das E / A-Subsystem muss nicht unbedingt wissen, ob es sich bei den Daten, die es gerade liest oder auf die Festplatte schreibt, tatsächlich um Programmcode, lesbaren Text oder Zahlen handelt. Es sind alles nur Teile, die durch die Maschine transportiert werden. Lassen Sie den Programmcode sich mit den Schreibproblemen befassen.

Klaws
quelle
0

Das tut es nicht. Tun sie es!

Oder Ihren Compiler / Interpreter.

Wenn der Computer angewiesen wird, die 0Nummer als Nummer hinzuzufügen , wird er dies tun. Wenn sie Computer sagen , das drucken Daten nach Reichweite zu stoppen 0, als " \0'Zeichen, es wird es tun.

Sprachen verfügen über Mechanismen, um den Umgang mit Daten sicherzustellen. In C haben Variablen Typen wie int, floatund char, und der Compiler generiert für jeden Datentyp die richtigen Anweisungen. Mit C können Sie jedoch Daten von einer Variablen in eine andere Variable eines anderen Typs umwandeln, wobei auch ein Zeiger als Zahl verwendet werden kann. Für den Computer sind alle Teile gleich.

Carlos Prado
quelle
0

Ein Nullzeichen ist ein Byte und ein Int ohne Vorzeichen ist zwei Bytes.

Quentin 2
quelle