Conceptul de „ număr magic ” în programare are trei semnificații:
Un număr magic , sau semnătură , este un număr întreg sau constantă de text folosită pentru a identifica în mod unic o resursă sau date . Un astfel de număr în sine nu are nicio semnificație și poate provoca nedumerire dacă apare în codul programului fără contextul sau comentariul adecvat , în timp ce o încercare de a-l schimba cu altul, chiar apropiat ca valoare, poate duce la consecințe absolut imprevizibile. Din acest motiv, astfel de numere au fost numite în mod ironic numere magice . În prezent, acest nume este ferm înrădăcinat ca termen . De exemplu, orice clasă de limbaj Java compilată începe cu un „număr magic” hexazecimal0xCAFEBABE . Al doilea exemplu binecunoscut este că orice fișier executabil Microsoft Windows cu extensia .exe începe cu o secvență de octeți 0x4D5A(care corespunde caracterelor ASCII MZ - inițialele lui Mark Zbikowski , unul dintre creatorii MS-DOS ). Un exemplu mai puțin cunoscut este indicatorul neinițializat din Microsoft Visual C++ (din versiunea din 2005 a Microsoft Visual Studio), care în modul de depanare este 0xDEADBEEF.
Pe sistemele de operare asemănătoare UNIX, tipul unui fișier este de obicei determinat de semnătura fișierului, indiferent de extensia numelui acestuia. Ele oferă un utilitar standard pentru a interpreta semnătura fișierului file.
De asemenea, „numere magice” este o practică proastă de programare atunci când o valoare numerică apare în textul sursă și semnificația acesteia nu este evidentă. De exemplu, un fragment ca acesta, scris în Java , ar fi rău:
drawSprite ( 53 , 320 , 240 );Este dificil pentru cineva care nu a scris un program să înțeleagă ce este 53, 320 sau 240. Dar dacă acest cod este rescris, totul cade la locul său.
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 );Acum este clar: acest cod afișează un sprite în centrul ecranului - punctul încrucișat al vederii. În majoritatea limbajelor de programare, toate valorile utilizate pentru astfel de constante vor fi calculate în timpul compilării și înlocuite în locurile în care sunt utilizate valorile ( pliere constantă ). Prin urmare, o astfel de modificare a textului sursă nu afectează performanța programului.
În plus, numerele magice sunt o sursă potențială de erori în program:
Uneori, numerele magice rănesc codul multiplatform [1] . Ideea este că în C în sistemele de operare pe 32 și 64 de biți, dimensiunea tipurilor char, shortși este garantată long long, în timp ce dimensiunea int, long, size_tși ptrdiff_tpoate varia (pentru primele două, în funcție de preferințele dezvoltatorilor de compilatoare, pt. ultimele două, în funcție de adâncimea de biți a sistemului țintă). În codul vechi sau prost scris, pot exista „numere magice” care indică dimensiunea unui tip - atunci când treceți la mașini cu o adâncime de biți diferită, acestea pot duce la erori subtile.
De exemplu:
const size_t NUMBER_OF_ELEMENTS = 10 ; lung a [ NUMBER_OF_ELEMENTS ]; memset ( a , 0 , 10 * 4 ); // greșit - se presupune că lung este de 4 octeți, folosește numărul magic de elemente memset ( a , 0 , NUMBER_OF_ELEMENTS * 4 ); // greșit - se presupune că lung este de 4 octeți memset ( a , 0 , NUMBER_OF_ELEMENTS * sizeof ( long )); // nu este complet corectă - duplicarea numelui tipului (dacă tipul se schimbă, va trebui să schimbați și aici) memset ( a , 0 , NUMBER_OF_ELEMENTS * sizeof ( a [ 0 ])); // corect, optim pentru matrice dinamice de dimensiune diferită de zero memset ( a , 0 , sizeof ( a )); // corect, optim pentru matrice staticeNu toate numerele trebuie convertite în constante. De exemplu, cod în Delphi :
pentru i := 0 to Count - 1 do ...Semnificația numerelor 0 și 1 este clară și nu este nevoie de o explicație suplimentară.