Begreppet " magiskt nummer " i programmering har tre betydelser:
Ett magiskt tal , eller signatur , är ett heltal eller en textkonstant som används för att unikt identifiera en resurs eller data . En sådan siffra i sig har ingen betydelse och kan orsaka förvirring om den förekommer i programkoden utan lämplig kontext eller kommentar , medan ett försök att ändra det till ett annat, till och med nära i värde, kan leda till helt oförutsägbara konsekvenser. Av denna anledning har sådana siffror ironiskt nog kallats magiska siffror . För närvarande är detta namn fast förankrat som en term . Till exempel börjar alla kompilerade Java - språkklasser med ett hexadecimalt "magiskt tal" 0xCAFEBABE. Det andra välkända exemplet är att alla körbara Microsoft Windows-filer med filtillägget .exe börjar med en sekvens av byte 0x4D5A(vilket motsvarar ASCII - tecknen MZ - initialerna för Mark Zbikowski , en av skaparna av MS-DOS ). Ett mindre känt exempel är den oinitierade pekaren i Microsoft Visual C++ (sedan 2005 års version av Microsoft Visual Studio), som i felsökningsläge är 0xDEADBEEF.
På UNIX-liknande operativsystem bestäms typen av en fil vanligtvis av filens signatur, oavsett dess namntillägg. De tillhandahåller ett standardverktyg för att tolka filsignaturen file.
Dessutom är "magiska siffror" en dålig programmeringspraxis när ett numeriskt värde förekommer i källtexten och dess betydelse inte är uppenbar. Till exempel skulle ett utdrag som detta, skrivet i Java , vara dåligt:
drawSprite ( 53 , 320 , 240 );Det är svårt för någon som inte har skrivit ett program att förstå vad 53, 320 eller 240 är. Men om den här koden skrivs om faller allt på plats.
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 );Nu är det klart: den här koden visar en sprite i mitten av skärmen - siktets hårkors. I de flesta programmeringsspråk kommer alla värden som används för sådana konstanter att beräknas vid kompilering och ersättas på de platser där värdena används ( konstant veck ). Därför försämrar inte en sådan ändring av källtexten programmets prestanda.
Dessutom är magiska siffror en potentiell källa till fel i programmet:
Ibland skadar magiska siffror plattformsoberoende kod [1] . Poängen är att i C i 32-bitars och 64-bitars operativsystem är storleken på typer char, shortoch garanterad long long, medan storleken på int, long, size_toch ptrdiff_tkan variera (för de två första, beroende på kompilatorutvecklarnas preferenser, för de två sista, beroende på bitdjupet i målsystemet). I gammal eller dåligt skriven kod kan det finnas "magiska siffror" som indikerar storleken på en typ - när man flyttar till maskiner med ett annat bitdjup kan de leda till subtila fel.
Till exempel:
const size_t NUMBER_OF_ELEMENTS = 10 ; lång a [ NUMBER_OF_ELEMENTS ]; memset ( a , 0 , 10 * 4 ); // fel - lång antas vara 4 byte, använder det magiska antalet element memset ( a , 0 , NUMBER_OF_ELEMENTS * 4 ); // fel - lång antas vara 4 byte memset ( a , 0 , NUMBER_OF_ELEMENTS * storleken på ( lång )); // inte helt korrekt - duplicering av typnamnet (om typen ändras måste du ändra här också) memset ( a , 0 , NUMBER_OF_ELEMENTS * sizeof ( a [ 0 ])); // korrekt, optimal för dynamiska arrayer av memset som inte är noll ( a , 0 , sizeof ( a )); // korrekt, optimal för statiska arrayerAlla tal behöver inte omvandlas till konstanter. Till exempel, kod i Delphi :
för i := 0 för att räkna - 1 gör ...Innebörden av siffrorna 0 och 1 är tydlig och ingen ytterligare förklaring behövs.