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.