Loading AI tools
Из Википедии, свободной энциклопедии
Понятие «Магическое число» в программировании имеет три значения:
Магическое число, или сигнатура, — целочисленная или текстовая константа, используемая для однозначной идентификации ресурса или данных. Такое число само по себе не несёт никакого смысла и может вызвать недоумение, встретившись в коде программы без соответствующего контекста или комментария, при этом попытка изменить его на другое, даже близкое по значению, может привести к абсолютно непредсказуемым последствиям. По этой причине подобные числа были иронично названы магическими. В настоящее время это название прочно закрепилось как термин. Например, любой откомпилированный класс языка Java начинается с шестнадцатеричного «магического числа» 0xCAFEBABE
. Второй широко известный пример — любой исполняемый файл ОС Microsoft Windows с расширением .exe начинается с последовательности байт 0x4D5A
(что соответствует ASCII-символам MZ — инициалы Марка Збиковски, одного из создателей MS-DOS). Менее известным примером является неинициализированный указатель в Microsoft Visual C++ (начиная с 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);
Теперь понятно: этот код выводит в центр экрана спрайт — перекрестие прицела. В большинстве языков программирования все значения, используемые для таких констант, будут вычислены ещё на этапе компиляции и подставлены в места использования значений (свёртка констант). Поэтому такое изменение исходного текста не ухудшает быстродействие программы.
Кроме того, магические числа — потенциальный источник ошибок в программе:
Иногда магические числа вредят кроссплатформенности кода[1]. Дело в том, что в Си в 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 понятен, и дальнейшего объяснения не требуется.
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.