Как можете да определите разликата между ASCII в двоичен и същия десетичен в двоичен?


Отговор 1:

По принцип не можете, не само от битовете. Например числото 00111001 в двоичен код: може да е числото 57, но може да бъде и ASCII цифрата „9“.

Това каза, на практика често можете да кажете разликата. Защото ще имате някаква представа каква трябва да бъде стойността, с която работите. Помислете за следната функция C, която има ярка грешка в нея:

int print (int n) {char buf [1]; int i; i = 3 * n + 2; sprintf (buf, "% i \ n", i); поставя (Buf); връщане i; }

Тя изчислява, за всяко цяло число n, стойността 3 * n + 2, изхвърля тази стойност в конзолата и връща стойността като цяло число. Въпреки това, можете да забележите, когато тествате тази функция, че ако входът е, да речем 9, той извежда правилния резултат 29 на конзолата. Но тя ще върне грешната стойност, в този случай стойността 57. И това може да ви даде някаква представа какво се случва тук, тъй като ще забележите, че 57 е ASCII представяне на числото 9 и това се случва да бъде последната цифра на резултата.

След това правите някои експерименти и установявате, че това е вярно винаги, когато резултатът е двуцифрено число. Например, при n = 5 резултатът трябва да е 17, но вместо това резултатът е 55, ASCII представяне на цифрата „7“.

И когато резултатът има повече от 2 цифри, резултатът е още по-странен. Например, при n = 50, правилният резултат 152 се изхвърля на конзолата, но връщащата се стойност е 12853 в десетична или 0x3235 в шестнадесетична. Може да забележите, че това е ASCII представяне на низа “25” или последните две цифри на резултата, в обратен ред!

И така, какво се случва тук? Забележете, че буферът за символи има място само за един знак! Функцията sprintf () в C не проверява за буфер надхвърляне, така че с радост ще запише изхода си в паметта, насочена към buf, презаписвайки байтовете веднага след байтовете, запазени за buf, ако buf е твърде малък. В този случай това са байтовете, запазени за цяло число i, и те се презаписват. И тъй като стойността на i след това се използва като връщаща стойност на тази функция, връщащата се стойност ще е неправилна.

Остава само един въпрос: защо връщащата стойност съдържа последните ASCII цифри на резултата, но в обратен ред? Това се случва, защото (ако приемем, че работите на компютър) байтовете от цяло число се съхраняват „по грешен начин“. Например 32-битовото цяло число 0x12345678 се съхранява като байтове 0x78 0x56 0x34 0x12 в паметта.

И така, когато входът е n = 50, първата цифра на резултата ще бъде запаметена в буф, докато втората и третата цифра на резултата ще се окажат в i, която след това ще стане в байтове, 0x35 0x32 0x00 0x00. И това представлява стойността 0x3235 = 12853 в десетични, когато се интерпретира като 32-битово число.

Като последна забележка: ако реално опитате това на вашата машина, резултатите може да са различни, тъй като ефектите от този тип грешки са силно зависими от вътрешната работа на вашата машина и вашия компилатор. Например, смартфонът най-често ще съхранява байтовете си в правилния ред, така че в резултат ще получите различно число. И вашият компилатор може да запази повече от 1 байт за buf поради проблеми с подравняването на паметта, или може да съхранява buf и i обратното (първо в паметта, после в buf). Или може да оптимизира i away, като запазва резултата само в регистър на процесора. В този случай резултатът ще бъде правилен, но нещо друго в паметта ще бъде повредено.

Като цяло, ако програмите съдържат такива грешки, всички залози са за това какво всъщност ще се случи.


Отговор 2:

Ако 48 е представяне на ASCII на числото нула, а 57 е представяне на ASCII на девет, тогава най-малко значимото хапане е реално представената цифра:

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

или просто; извадете 48, за да ви дам числото.