Maaginen numero (ohjelmointi)

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 10. joulukuuta 2019 tarkistetusta versiosta . tarkastukset vaativat 10 muokkausta .

Käsitteellä " Maaginen numero " ohjelmoinnissa on kolme merkitystä:

Tietojen allekirjoitus

Maaginen luku tai allekirjoitus on kokonaisluku- tai tekstivakio , jota käytetään yksilöimään resurssi tai data . Tällaisella numerolla ei sinänsä ole mitään merkitystä ja se voi aiheuttaa hämmennystä, jos se esiintyy ohjelmakoodissa ilman asianmukaista kontekstia tai kommenttia , kun taas yritys muuttaa se toiseksi, jopa lähellä arvoa, voi johtaa täysin arvaamattomiin seurauksiin. Tästä syystä tällaisia ​​numeroita on ironisesti kutsuttu maagisiksi numeroiksi . Tällä hetkellä tämä nimi on lujasti juurtunut termiksi . Esimerkiksi mikä tahansa käännetty Java -kieliluokka alkaa heksadesimaaliluvulla "magic number" 0xCAFEBABE. Toinen hyvin tunnettu esimerkki on, että mikä tahansa Microsoft Windows -suoritettava tiedosto, jonka laajennus on .exe, alkaa tavujonolla 0x4D5A(joka vastaa ASCII - merkkejä MZ  - Mark Zbikowskin , yhden MS-DOS :n luojista, nimikirjaimet ). Vähemmän tunnettu esimerkki on alustamaton osoitin Microsoft Visual C++:ssa (vuodesta 2005 lähtien Microsoft Visual Studion versio), joka virheenkorjaustilassa on 0xDEADBEEF.

UNIX-tyyppisissä käyttöjärjestelmissä tiedoston tyyppi määräytyy yleensä tiedoston allekirjoituksen mukaan, riippumatta sen nimitunnisteesta. Ne tarjoavat tavallisen apuohjelman tiedoston allekirjoituksen tulkitsemiseen file.

Huono ohjelmointikäytäntö

Myös "maagiset numerot" on huono ohjelmointikäytäntö, kun lähdetekstissä esiintyy numeerinen arvo ja sen merkitys ei ole ilmeinen. Esimerkiksi tällainen Java -kielellä kirjoitettu katkelma olisi huono:

drawSprite ( 53 , 320 , 240 );

Sen, joka ei ole kirjoittanut ohjelmaa, on vaikea ymmärtää, mikä on 53, 320 tai 240. Mutta jos tämä koodi kirjoitetaan uudelleen, kaikki loksahtaa paikoilleen.

lopullinen int SCREEN_WIDTH = 640 ; lopullinen int SCREEN_HEIGHT = 480 ; lopullinen int SCREEN_X_CENTER = SCREEN_WIDTH / 2 ; lopullinen int SCREEN_Y_CENTER = SCREEN_HEIGHT / 2 ; lopullinen int SPRITE_CROSSHAIR = 53 ; ... drawSprite ( SPRITE_CROSSHAIR , SCREEN_X_CENTER , SCREEN_Y_CENTER );

Nyt se on selvää: tämä koodi näyttää spriten näytön keskellä  - tähtäimen hiusristikon. Useimmissa ohjelmointikielissä kaikki tällaisille vakioille käytetyt arvot lasketaan käännöshetkellä ja korvataan paikkoihin, joissa arvoja käytetään ( vakiokerta ). Siksi tällainen muutos lähdetekstissä ei heikennä ohjelman suorituskykyä.

Lisäksi maagiset numerot ovat mahdollinen virhelähde ohjelmassa:

  • Jos samaa maagista numeroa käytetään useammin kuin kerran ohjelmassa (tai sitä voitaisiin mahdollisesti käyttää), sen muuttaminen edellyttää jokaisen esiintymän muokkaamista (eikä vain nimetyn vakion arvon muokkaamista). Jos kaikkia tapahtumia ei korjata, tapahtuu vähintään yksi virhe.
  • Ainakin yhdessä tapauksessa maaginen numero voi olla aluksi kirjoitettu väärin, ja tämä on melko vaikea havaita.
  • Maaginen luku voi riippua implisiittisestä parametrista tai muusta maagisesta numerosta. Jos nämä riippuvuudet, joita ei ole nimenomaisesti tunnistettu, eivät täyty, tapahtuu vähintään yksi virhe.
  • Muutamalla yhden maagisen luvun esiintymiä on mahdollista muuttaa virheellisesti toista maagista numeroa, joka on riippumaton mutta jolla on sama numeerinen arvo.

Maagiset numerot ja cross-platform

Joskus maagiset numerot vahingoittavat alustojen välistä koodia [1] . Asia on siinä, että C :ssä 32- ja 64-bittisissä käyttöjärjestelmissä , ja -tyyppien koko charon shorttaattu long long, kun taas int, long, size_tja koko ptrdiff_tvoi vaihdella (kahdelle ensimmäiselle kääntäjien kehittäjien mieltymyksistä riippuen kaksi viimeistä kohdejärjestelmän bittisyvyydestä riippuen). Vanhassa tai huonosti kirjoitetussa koodissa voi olla "maagisia numeroita", jotka osoittavat tyypin koon - siirryttäessä koneisiin, joilla on eri bittisyvyys, ne voivat johtaa hienovaraisiin virheisiin.

Esimerkiksi:

const size_t NUMBER_OF_ELEMENTS = 10 ; pitkä a [ NUMBER_OF_ELEMENTS ]; memset ( a , 0 , 10 * 4 ); // väärin - pitkän oletetaan olevan 4 tavua, käyttää maagista elementtien lukumäärää memset ( a , 0 , NUMBER_OF_ELEMENTS * 4 ); // väärin - pitkän oletetaan olevan 4 tavua memset ( a , 0 , NUMBER_OF_ELEMENTS * sizeof ( long )); // ei täysin oikein - tyypin nimen kopio (jos tyyppi muuttuu, joudut muuttamaan myös täällä) memset ( a , 0 , NUMBER_OF_ELEMENTS * sizeof ( a [ 0 ])); // oikea, optimaalinen nollasta poikkeaville dynaamisille taulukoille ( a , 0 , sizeof ( a ) ); // oikein, optimaalinen staattisille taulukoille

Numerot, jotka eivät ole maagisia

Kaikkia lukuja ei tarvitse muuntaa vakioiksi. Esimerkiksi koodi Delphissä :

for i := 0 to Count - 1 do ...

Numeroiden 0 ja 1 merkitys on selvä, eikä sen enempää selittelyä tarvita.

Katso myös

Muistiinpanot

  1. 20 sudenkuoppaa C++-koodin siirtämisessä 64-bittiselle alustalle . Haettu 31. lokakuuta 2008. Arkistoitu alkuperäisestä 15. elokuuta 2010.