Wie können Sie den Unterschied zwischen ASCII in Binär und derselben Dezimalzahl in Binär erkennen?


Antwort 1:

Im Allgemeinen können Sie nicht, nicht nur durch die Bits. Zum Beispiel die Nummer 00111001 in Binärform: Es könnte durchaus die Nummer 57 sein, aber es könnte auch die ASCII-Ziffer „9“ sein.

In der Praxis kann man jedoch oft den Unterschied erkennen. Weil Sie eine Vorstellung davon haben, mit welchem ​​Wert Sie arbeiten sollten. Betrachten Sie die folgende C-Funktion, die einen krassen Fehler enthält:

int print (int n) {char buf [1]; int i; i = 3 · n + 2; sprintf (buf, "% i \ n", i); setzt (buf); return i; }}

Es berechnet für jede Ganzzahl n den Wert 3 * n + 2, gibt diesen Wert an die Konsole aus und gibt den Wert als Ganzzahl zurück. Beim Testen dieser Funktion stellen Sie jedoch möglicherweise fest, dass bei einer Eingabe von beispielsweise 9 das richtige Ergebnis 29 auf die Konsole gedruckt wird. Es wird jedoch der falsche Wert zurückgegeben, in diesem Fall der Wert 57. Und das kann Ihnen einen Hinweis darauf geben, was hier passiert, da Sie feststellen werden, dass 57 die ASCII-Darstellung der Zahl 9 ist und dies zufällig ist die letzte Ziffer des Ergebnisses.

Anschließend experimentieren Sie und stellen fest, dass dies immer dann zutrifft, wenn das Ergebnis eine zweistellige Zahl ist. Zum Beispiel sollte mit n = 5 das Ergebnis 17 sein, aber stattdessen ist das Ergebnis 55, die ASCII-Darstellung der Ziffer „7“.

Und wenn das Ergebnis mehr als 2 Stellen hat, ist das Ergebnis noch seltsamer. Beispielsweise wird mit n = 50 das korrekte Ergebnis 152 auf der Konsole ausgegeben, aber der Rückgabewert ist 12853 in Dezimalzahl oder 0x3235 in Hexadezimalzahl. Möglicherweise stellen Sie fest, dass dies die ASCII-Darstellung der Zeichenfolge „25“ oder die letzten beiden Ziffern des Ergebnisses in umgekehrter Reihenfolge ist!

Also, was passiert hier? Beachten Sie, dass der Zeichenpuffer nur Platz für ein einzelnes Zeichen bietet! Die sprintf () -Funktion in C prüft nicht auf Pufferüberläufe, schreibt also ihre Ausgabe gerne in den Speicher, auf den buf zeigt, und überschreibt die Bytes unmittelbar nach den für buf reservierten Bytes, wenn buf zu klein ist. In diesem Fall sind dies die Bytes, die für die Ganzzahl i reserviert sind, und sie werden überschrieben. Und da der Wert von i dann als Rückgabewert dieser Funktion verwendet wird, ist der Rückgabewert falsch.

Es bleibt nur eine Frage: Warum enthält der Rückgabewert die letzten ASCII-Ziffern des Ergebnisses, jedoch in umgekehrter Reihenfolge? Dies liegt daran, dass (vorausgesetzt, Sie arbeiten an einem PC) die Bytes einer Ganzzahl „falsch herum“ gespeichert werden. Beispielsweise wird die 32-Bit-Ganzzahl 0x12345678 als Byte 0x78 0x56 0x34 0x12 im Speicher gespeichert.

Wenn also die Eingabe n = 50 ist, wird die erste Ziffer des Ergebnisses in buf gespeichert, während die zweite und dritte Ziffer des Ergebnisses in i enden, was dann in Bytes 0x35 0x32 0x00 0x00 wird. Und dies stellt den Wert 0x3235 = 12853 in Dezimalzahl dar, wenn er als 32-Bit-Zahl interpretiert wird.

Als letzte Anmerkung: Wenn Sie dies tatsächlich auf Ihrem Computer versuchen, können die Ergebnisse durchaus unterschiedlich sein, da die Auswirkungen dieser Art von Fehler stark vom Innenleben Ihres Computers und Ihres Compilers abhängen. Beispielsweise speichert ein Smartphone seine Bytes meistens in der richtigen Reihenfolge, sodass Sie eine andere Nummer erhalten. Und Ihr Compiler kann aufgrund von Speicherausrichtungsproblemen möglicherweise mehr als 1 Byte für buf reservieren, oder er speichert buf und i umgekehrt (i zuerst im Speicher, dann buf). Oder es kann i weg optimieren, indem nur das Ergebnis in einem CPU-Register gespeichert wird. In diesem Fall ist das Ergebnis korrekt, aber etwas anderes im Speicher ist beschädigt.

Wenn Programme solche Fehler enthalten, beziehen sich alle Wetten darauf, was tatsächlich passieren wird.


Antwort 2:

Wenn 48 die ASCII-Darstellung der Zahl Null und 57 die ASCII-Darstellung der Zahl Neun ist, ist das niedrigstwertige Halbbyte die tatsächlich dargestellte Ziffer:

0000 0000-0011 0000 = 32 + 16 + 0 = 48

0000 0001-0011 0001

0000 0010-0011 0010

0000 0011-0011 0011

0000 0100-0011 0100

0000 0101-0011 0101

0000 0110-0011 0110

0000 0111-0011 0111

0000 1000-0011 1000

0000 1001-0011 1001 = 32 + 16 + 8 + 1 = 57

oder einfach; subtrahieren Sie 48, um die Zahl zu erhalten.