Поняття «Магічне число» в програмуванні має три значення:
- Сигнатура даних
- Виділені унікальні значення, які не повинні збігатися з іншими значеннями (наприклад, UUID)
- Погана практика програмування.
Сигнатура даних
Магічне число, або сигнатура, — цілочисельна або текстова константа, яка використовується для однозначної ідентифікації ресурсу або даних. Таке число саме по собі не має ніякого сенсу і може викликати здивування, зустрівшись у коді програми без відповідного контексту або коментаря, при цьому спроба змінити його на інше, навіть близьке за значенням, може спричинити абсолютно непередбачувані наслідки. З цієї причини такі числа іронічно називають магічними. В цей час ця назва міцно закріпилася як термін. Наприклад, будь-який відкомпільований клас мови Java починається з шістнадцятирічного «магічного числа» 0xCAFEBABE
. Інший відомий приклад — будь-який виконуваний файл ОС Microsoft Windows з розширенням .exe починається з послідовності байтів 0x4D5A
(що відповідає ASCII-символів MZ — ініціали , одного з творців MS-DOS). Менш відомим прикладом є неініціалізований вказівник у (починаючи з 2005 версії Microsoft Visual Studio), який в режимі налагодження має адресу 0xDEADBEEF
.
В UNIX-подібних операційних системах тип файлу зазвичай визначається за сигнатурою файлу, незалежно від розширення його назви. Для інтерпретації сигнатури файлу в них призначена стандартна утиліта file
.
Погана практика програмування
Також «магічними числами» називають погану практику програмування, коли у тексті програми зустрічається числове значення, сенс якого не очевидний. Наприклад, такий фрагмент, написаний на Java, буде поганим:
drawSprite(53, 320, 240);
Людині, яка не є автором програми, важко зрозуміти, що таке 53, 320 або 240. Але якщо цей код переписати, все стає на свої місця:
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);
Тепер зрозуміло: ця інструкція виводить у центр екрана спрайт — перехрестя прицілу. В більшості мов програмування всі значення, які використовуються для таких констант, будуть пораховані ще на етапі компіляції й підставлені в місця їх використання. Тому така зміна вихідного тексту не погіршує швидкодії програми.
Крім того, магічні числа — потенційне джерело помилок у програмі:
- Якщо одне і те саме магічне число використовується в програмі більше одного разу (або потенційно може використовуватися), то для зміни його значення потрібно буде виправити кожне входження (замість одного виправлення значення іменованої константи). Якщо не будуть виправлені всі входження, виникне принаймні одна помилка.
- Принаймні в одному зі входжень магічне число може бути написане з помилкою спочатку, і це досить складно виявити.
- Магічне число може залежати від неявного параметра або іншого магічного числа. Якщо ці залежності, не виділені явно, не будуть задоволені, виникне принаймні одна помилка.
- Під час модифікації входжень одного магічного числа можна помилково змінити інше магічне число, незалежне, але з таким самим числовим значенням.
Магічні числа і кросплатформність
Іноді магічні числа шкодять кросплатформності коду. Річ у тому, що в Сі в 32- і 64-бітних ОС гарантується розмір типів char
, short
і long long
, тоді як розмір int
, long
, size_t
і ptrdiff_t
може змінюватися (у перших двох — залежно від уподобань розробників компіляторів, в останніх двох — залежно від розрядності цільової системи). У старому або невміло написаному коді можуть зустрічатися «магічні числа», що означають розмір певного типу — під час переходу на машини з іншою розрядністю вони можуть призвести до невловних помилок.
Наприклад:
const size_t NUMBER_OF_ELEMENTS = 10; long a[NUMBER_OF_ELEMENTS]; memset(a, 0, 10 * 4); // неправильно — йдеться про те, що long дорівнює 4 байтам, використовується магічне число елементів memset(a, 0, NUMBER_OF_ELEMENTS * 4); // неправильно — йдеться про те, що long дорівнює 4 байтам memset(a, 0, NUMBER_OF_ELEMENTS * sizeof(long)); // не зовсім правильно — дублювання назви типу (якщо зміниться тип, то доведеться змінити й тут) memset(a, 0, NUMBER_OF_ELEMENTS * sizeof(a[0])); // правильно, оптимально для динамічних масивів ненульового розміру memset(a, 0, sizeof(a)); // правильно, оптимально для статичних масивів
Числа, які не є магічними
Не всі числа потрібно переносити в константи. Наприклад, у такому коді на Delphi:
for i:=0 to Count-1 do ...
сенс чисел 0 і 1 цілком зрозумілий.
Див. також
Примітки
- . Архів оригіналу за 15 серпня 2010. Процитовано 10 серпня 2020.
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Ponyattya Magichne chislo v programuvanni maye tri znachennya Signatura danih Vidileni unikalni znachennya yaki ne povinni zbigatisya z inshimi znachennyami napriklad UUID Pogana praktika programuvannya Signatura danihMagichne chislo abo signatura cilochiselna abo tekstova konstanta yaka vikoristovuyetsya dlya odnoznachnoyi identifikaciyi resursu abo danih Take chislo same po sobi ne maye niyakogo sensu i mozhe viklikati zdivuvannya zustrivshis u kodi programi bez vidpovidnogo kontekstu abo komentarya pri comu sproba zminiti jogo na inshe navit blizke za znachennyam mozhe sprichiniti absolyutno neperedbachuvani naslidki Z ciyeyi prichini taki chisla ironichno nazivayut magichnimi V cej chas cya nazva micno zakripilasya yak termin Napriklad bud yakij vidkompilovanij klas movi Java pochinayetsya z shistnadcyatirichnogo magichnogo chisla 0xCAFEBABE Inshij vidomij priklad bud yakij vikonuvanij fajl OS Microsoft Windows z rozshirennyam exe pochinayetsya z poslidovnosti bajtiv 0x4D5A sho vidpovidaye ASCII simvoliv MZ iniciali odnogo z tvorciv MS DOS Mensh vidomim prikladom ye neinicializovanij vkazivnik u Microsoft Visual C pochinayuchi z 2005 versiyi Microsoft Visual Studio yakij v rezhimi nalagodzhennya maye adresu 0xDEADBEEF V UNIX podibnih operacijnih sistemah tip fajlu zazvichaj viznachayetsya za signaturoyu fajlu nezalezhno vid rozshirennya jogo nazvi Dlya interpretaciyi signaturi fajlu v nih priznachena standartna utilita file Pogana praktika programuvannyaTakozh magichnimi chislami nazivayut poganu praktiku programuvannya koli u teksti programi zustrichayetsya chislove znachennya sens yakogo ne ochevidnij Napriklad takij fragment napisanij na Java bude poganim drawSprite 53 320 240 Lyudini yaka ne ye avtorom programi vazhko zrozumiti sho take 53 320 abo 240 Ale yaksho cej kod perepisati vse staye na svoyi miscya 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 Teper zrozumilo cya instrukciya vivodit u centr ekrana sprajt perehrestya pricilu V bilshosti mov programuvannya vsi znachennya yaki vikoristovuyutsya dlya takih konstant budut porahovani she na etapi kompilyaciyi j pidstavleni v miscya yih vikoristannya Tomu taka zmina vihidnogo tekstu ne pogirshuye shvidkodiyi programi Krim togo magichni chisla potencijne dzherelo pomilok u programi Yaksho odne i te same magichne chislo vikoristovuyetsya v programi bilshe odnogo razu abo potencijno mozhe vikoristovuvatisya to dlya zmini jogo znachennya potribno bude vipraviti kozhne vhodzhennya zamist odnogo vipravlennya znachennya imenovanoyi konstanti Yaksho ne budut vipravleni vsi vhodzhennya vinikne prinajmni odna pomilka Prinajmni v odnomu zi vhodzhen magichne chislo mozhe buti napisane z pomilkoyu spochatku i ce dosit skladno viyaviti Magichne chislo mozhe zalezhati vid neyavnogo parametra abo inshogo magichnogo chisla Yaksho ci zalezhnosti ne vidileni yavno ne budut zadovoleni vinikne prinajmni odna pomilka Pid chas modifikaciyi vhodzhen odnogo magichnogo chisla mozhna pomilkovo zminiti inshe magichne chislo nezalezhne ale z takim samim chislovim znachennyam Magichni chisla i krosplatformnist Inodi magichni chisla shkodyat krosplatformnosti kodu Rich u tomu sho v Si v 32 i 64 bitnih OS garantuyetsya rozmir tipiv char short i long long todi yak rozmir int long size t i ptrdiff t mozhe zminyuvatisya u pershih dvoh zalezhno vid upodoban rozrobnikiv kompilyatoriv v ostannih dvoh zalezhno vid rozryadnosti cilovoyi sistemi U staromu abo nevmilo napisanomu kodi mozhut zustrichatisya magichni chisla sho oznachayut rozmir pevnogo tipu pid chas perehodu na mashini z inshoyu rozryadnistyu voni mozhut prizvesti do nevlovnih pomilok Napriklad const size t NUMBER OF ELEMENTS 10 long a NUMBER OF ELEMENTS memset a 0 10 4 nepravilno jdetsya pro te sho long dorivnyuye 4 bajtam vikoristovuyetsya magichne chislo elementiv memset a 0 NUMBER OF ELEMENTS 4 nepravilno jdetsya pro te sho long dorivnyuye 4 bajtam memset a 0 NUMBER OF ELEMENTS sizeof long ne zovsim pravilno dublyuvannya nazvi tipu yaksho zminitsya tip to dovedetsya zminiti j tut memset a 0 NUMBER OF ELEMENTS sizeof a 0 pravilno optimalno dlya dinamichnih masiviv nenulovogo rozmiru memset a 0 sizeof a pravilno optimalno dlya statichnih masiviv Chisla yaki ne ye magichnimi Ne vsi chisla potribno perenositi v konstanti Napriklad u takomu kodi na Delphi for i 0 to Count 1 do sens chisel 0 i 1 cilkom zrozumilij Div takozhHexspeak Shvidkij obernenij kvadratnij korinPrimitki Arhiv originalu za 15 serpnya 2010 Procitovano 10 serpnya 2020