Magické číslo (programování)

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 10. prosince 2019; kontroly vyžadují 10 úprav .

Pojem „ magické číslo “ v programování má tři významy:

Podpis dat

Magické číslo nebo podpis je celé číslo nebo textová konstanta používaná k jedinečné identifikaci zdroje nebo dat . Takové číslo samo o sobě nenese žádný význam a může způsobit zmatek, pokud se objeví v programovém kódu bez příslušného kontextu nebo komentáře , zatímco pokus o jeho změnu na jiné, byť hodnotou blízkou, může vést k naprosto nepředvídatelným následkům. Z tohoto důvodu byla taková čísla ironicky nazývána magická čísla . V současnosti je toto jméno pevně zakořeněno jako pojem . Například jakákoli kompilovaná třída jazyka Java začíná hexadecimálním „magickým číslem“ 0xCAFEBABE. Druhým známým příkladem je, že jakýkoli spustitelný soubor Microsoft Windows s příponou .exe začíná posloupností bajtů 0x4D5A(což odpovídá ASCII znakům MZ  – iniciálám Marka Zbikowského , jednoho z tvůrců MS-DOSu ). Méně známým příkladem je neinicializovaný ukazatel v Microsoft Visual C++ (od verze 2005 Microsoft Visual Studio), který je v režimu ladění 0xDEADBEEF.

V operačních systémech podobných UNIX je typ souboru obvykle určen podpisem souboru, bez ohledu na jeho příponu. Poskytují standardní nástroj pro interpretaci podpisu souboru file.

Špatná programovací praxe

Také „magická čísla“ jsou špatnou programátorskou praxí, když se ve zdrojovém textu vyskytuje číselná hodnota a její význam není zřejmý. Například takový úryvek napsaný v Javě by byl špatný:

drawSprite ( 53 , 320 , 240 );

Pro někoho, kdo nenapsal program, je těžké pochopit, co je 53, 320 nebo 240. Ale pokud je tento kód přepsán, vše zapadne na své místo.

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

Nyní je to jasné: tento kód zobrazuje sprite ve středu obrazovky  - zaměřovací kříž zaměřovače. Ve většině programovacích jazyků budou všechny hodnoty použité pro takové konstanty vypočteny v době kompilace a nahrazeny místy, kde jsou hodnoty použity ( konstanta fold ). Taková změna ve zdrojovém textu tedy nezhorší výkon programu.

Magická čísla jsou navíc potenciálním zdrojem chyb v programu:

  • Pokud je stejné magické číslo v programu použito více než jednou (nebo by mohlo být potenciálně použito), pak jeho změna bude vyžadovat úpravu každého výskytu (místo pouhé úpravy hodnoty pojmenované konstanty). Pokud nejsou všechny výskyty opraveny, dojde alespoň k jedné chybě.
  • Alespoň v jednom z výskytů může být magické číslo zpočátku špatně napsáno, což je poměrně obtížné odhalit.
  • Magické číslo může záviset na implicitním parametru nebo jiném magickém čísle. Pokud tyto závislosti, které nejsou explicitně identifikovány, nejsou splněny, dojde alespoň k jedné chybě.
  • Při úpravě výskytů jednoho magického čísla je možné omylem změnit jiné magické číslo, které je nezávislé, ale má stejnou číselnou hodnotu.

Magická čísla a multiplatformní

Někdy magická čísla poškozují multiplatformní kód [1] . Jde o to, že v C v 32bitových a 64bitových operačních systémech je zaručena velikost typů char, shorta long long, zatímco velikost int, long, size_ta ptrdiff_tse může lišit (u prvních dvou, v závislosti na preferencích vývojářů kompilátorů, např. poslední dva, v závislosti na bitové hloubce cílového systému). Ve starém nebo špatně napsaném kódu se mohou vyskytovat „magická čísla“, která označují velikost typu – při přechodu na stroje s jinou bitovou hloubkou mohou vést k jemným chybám.

Například:

const size_t NUMBER_OF_ELEMENTS = 10 ; dlouhé a [ NUMBER_OF_ELEMENTS ]; memset ( a , 0 , 10 * 4 ); // špatně - předpokládá se, že délka je 4 bajty, používá magický počet prvků memset ( a , 0 , NUMBER_OF_ELEMENTS * 4 ); // špatně - předpokládá se, že long je 4 byte memset ( a , 0 , NUMBER_OF_ELEMENTS * sizeof ( long )); // ne zcela správně - duplikace názvu typu (pokud se typ změní, budete muset změnit i zde) memset ( a , 0 , NUMBER_OF_ELEMENTS * sizeof ( a [ 0 ])); // správné, optimální pro dynamická pole s nenulovou velikostí memset ( a , 0 , sizeof ( a )); // správné, optimální pro statická pole

Čísla, která nejsou magická

Ne všechna čísla je nutné převádět na konstanty. Například kód v Delphi :

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

Význam čísel 0 a 1 je jasný a není třeba dalšího vysvětlování.

Viz také

Poznámky

  1. 20 úskalí portování kódu C++ na 64bitovou platformu . Získáno 31. října 2008. Archivováno z originálu 15. srpna 2010.