Hogyan lehet megmondani a különbséget az ASCII bináris és az azonos decimális érték között binárisan?


Válasz 1:

Általában nem, nem csak a bittel. Például, a 00111001 szám bináris formában: lehet, hogy az 57, de lehet, hogy az ASCII „9” szám is.

A gyakorlatban azonban gyakran megmondhatjuk a különbséget. Mert van némi ötlete, hogy milyen értékűnek kell lennie, hogy dolgozik. Fontolja meg a következő C függvényt, amelyben egy feltűnő hiba van:

int nyomtatás (int n) {char buf [1]; int i; i = 3 * n + 2; sprintf (buf, "% i \ n", i); helyezi (buf); visszatérés i; }

Kiszámítja minden n egész számra a 3 * n + 2 értéket, ezt az értéket a konzolra dobja, és egész értékként adja vissza. Ennek a funkciónak a tesztelésekor azonban észreveheti, hogy ha a bemenet mondjuk 9, akkor a megfelelő eredményt 29 nyomtatja ki a konzolra. De a helytelen értéket adja vissza, ebben az esetben az 57-ös értéket. És ez adhat neked bizonyos információt arról, hogy mi történik itt, mivel észre fogod venni, hogy az 57 a 9-es szám ASCII-ábrázolása, és ez történik az eredmény utolsó számjegye.

Ezután néhány kísérletet végez, és megállapítja, hogy ez igaz, amikor az eredmény két számjegyű szám. Például, ha n = 5, az eredménynek 17-nek kell lennie, az eredmény helyett 55, a „7” szám ASCII-ábrázolása.

És ha az eredmény több, mint 2 számjegy, az eredmény még furcsabb. Például, ha n = 50, akkor a helyes 152 eredményt a konzolra dobják, de a visszatérési érték 12853 decimális, vagy 0x3235 hexadecimális értékben. Előfordulhat, hogy ez a „25” karakterlánc ASCII ábrázolása, vagy az eredmény utolsó két számjegye, fordított sorrendben!

Szóval, mi történik itt? Vegye figyelembe, hogy a karakterpuffernek csak egy karakter számára van hely! A sprintf () függvény C-ben nem ellenőrzi a puffer túllépéseket, tehát boldogan írja a kimenetet a buf által megjelölt memóriába, és felülírja a bájtokat közvetlenül a buf számára fenntartott bájtok után, ha a buf túl kicsi. Ebben az esetben ezek az i egész szám számára fenntartott byte-ok, és felülíródnak. Mivel pedig i értékét használják e funkció visszatérési értékének, a visszatérési érték helytelen lesz.

Csak egy kérdés marad fenn: miért tartalmazza a visszatérési érték az eredmény utolsó ASCII számjegyeit, de fordított sorrendben? Ez akkor történik, mert (ha feltételezzük, hogy számítógépen dolgozik) egy egész szám bájtjait „rosszul fordítva” tárolják. Például a 32 bites 0x12345678 egész számot 0x78 0x56 0x34 0x12 bájtként tárolják a memóriában.

Tehát, ha a bemenet n = 50, az eredmény első számjegyét buf-ban tárolják, míg az eredmény második és harmadik számjegye i-ben végződik, amely bájtban 0x35 0x32 0x00 0x00 lesz. És ez jelenti a 0x3235 = 12853 értéket decimálisan, ha 32 bites számként értelmezzük.

Végül: ha ezt valóban kipróbálnád a gépeden, akkor az eredmények is különbözhetnek, mivel az ilyen típusú hibák hatása erősen függ a számítógép és a fordító belső működésétől. Például, egy okostelefon leggyakrabban a helyes sorrendben tárolja bájtjait, így eltérő számot kap. Lehet, hogy a fordító több mint 1 bájtot lefoglal a buf-ra a memória igazításával kapcsolatos problémák miatt, vagy tárolhatja a buf-ot és i-t fordítva (először a memóriában, majd a buf-ban). Vagy optimalizálhatja az i-t, ha az eredményt csak CPU-nyilvántartásban tartja. Ebben az esetben az eredmény helyes lesz, de valami más a memóriában megsérül.

Általában, ha a programok ilyen hibákat tartalmaznak, akkor minden fogadás arra vonatkozik, hogy mi fog történni.


Válasz 2:

Ha 48 a nulla szám ASCII reprezentációja és 57 a kilenc ASCII ábrázolása, akkor a legkevésbé jelentős rágcsálódás a ténylegesen ábrázolt számjegy:

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

vagy egyszerűen; kivon 48, hogy megkapja a számot.