Hvernig geturðu greint muninn á ASCII í tvöfaldri og sömu aukastaf í tvöfaldri?


svara 1:

Almennt geturðu ekki, ekki bara í gegnum bitana. Til dæmis númerið 00111001 á tvöfaldri formi: Það gæti verið talan 57, en það gæti líka verið ASCII númerið "9".

Í reynd geturðu þó oft séð muninn. Vegna þess að þú hefur hugmynd um hvaða gildi þú ættir að vinna með. Hugleiddu eftirfarandi C aðgerð, sem inniheldur geigvænlega villu:

int prenta (int n) {char buf [1]; int i; i = 3 * n + 2; sprintf (buf, "% i \ n", i); setur (buf); skila i; }}

Það reiknar gildi 3 * n + 2 fyrir hvert heiltölu n, gefur þetta gildi út á stjórnborðið og skilar gildinu sem heiltala. Hins vegar, þegar þú prófar þennan möguleika, gætirðu komist að því að ef þú slærð inn 9, til dæmis, verður rétt niðurstaða 29 prentuð á stjórnborðið. Hins vegar er rangt gildi skilað, í þessu tilfelli gildið 57. Og það getur gefið þér vísbendingu um hvað er að gerast hér, þar sem þú munt komast að því að 57 er ASCII framsetning tölunnar 9 og þetta verður síðasti tölustafurinn af niðurstöðunni.

Síðan gerðir þú tilraunir og kemst að því að þetta er rétt þegar niðurstaðan er tveggja stafa tala. Til dæmis, með n = 5, ætti niðurstaðan að vera 17, en í staðinn er niðurstaðan 55, ASCII framsetning tölunnar „7“.

Og ef niðurstaðan er með meira en 2 tölustafi, þá er útkoman enn skrýtnari. Til dæmis, með n = 50, er rétt niðurstaða 152 gefin út á vélinni, en skilagildið er 12853 í aukastaf eða 0x3235 í sextánsku tölu. Þú gætir komist að því að þetta er ASCII framsetning strengsins „25“ eða síðustu tveir tölustafir niðurstöðunnar í öfugri röð!

Svo hvað er að gerast hér? Athugaðu að stafatilboðið býður aðeins upp á pláss fyrir einn staf! Sprintf () aðgerðin í C athugar ekki hvort jafnalausir séu á biðminni, svo að hann vill skrifa framleiðsluna í minnið sem Buf vísar til og skrifar yfir bæturnar strax á eftir bítunum sem eru fráteknir fyrir buf ef buf er of lítið. Í þessu tilfelli eru þetta bæturnar sem eru fráteknir fyrir heiltöluna i og þeir eru ofskrifaðir. Og þar sem gildi i er síðan notað sem skilagildi þessarar aðgerðar, er skilagildið rangt.

Aðeins ein spurning er eftir: af hverju inniheldur ávöxtunargildið síðustu ASCII tölustafir niðurstöðunnar, en í öfugri röð? Þetta er vegna þess að (miðað við að þú sért að vinna í tölvu) eru bæti heiltölu geymd „á rangan hátt“. Til dæmis er 32-bita heiltala 0x12345678 geymd í minni sem bæti 0x78 0x56 0x34 0x12.

Þannig að ef inntakið er n = 50, þá er fyrsta tölustaf niðurstöðunnar geymd í buf, á meðan önnur og þriðja tölustaf niðurstöðunnar endar í i, sem verður þá bæti 0x35 0x32 0x00 0x00. Og þetta táknar gildi 0x3235 = 12853 í aukastaf ef það er túlkað sem 32-bita tala.

Að lokum, ef þú prófar þetta í tölvunni þinni, geta niðurstöðurnar verið breytilegar, vegna þess að áhrif þessara villna eru mjög háð innan tölvunnar og þýðandans. Til dæmis geymir snjallsími venjulega bæti sína í réttri röð svo þú fáir annað númer. Og þýðandinn þinn kann að panta meira en 1 bæti fyrir buf vegna minnisstillingarvandamála, eða það getur geymt buf og ég öfugt (ég fyrst í minni, síðan buf). Eða það getur hagrætt í burtu með því bara að geyma niðurstöðuna í CPU skrá. Í þessu tilfelli er niðurstaðan rétt, en eitthvað annað í minni er skemmt.

Ef forrit innihalda slíkar villur verða öll veðmál byggð á því sem raunverulega mun gerast.


svara 2:

Ef 48 er ASCII framsetning tölunnar núll og 57 er ASCII framsetning númersins níu, þá er minnsti merkjanlegi fjöldinn sem raunverulega er fulltrúi:

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

eða einfalt; draga 48 til að fá töluna.