Один хороший пример того, почему именованные константы полезны, можно найти в превосходной книге Kernighan and Pike (1999) Практика программирования.
§1.5 Магические числа
[...] Этот отрывок из программы для печати гистограммы буквенных частот на терминале с адресом курсора 24 на 80 излишне непрозрачен из-за множества магических чисел:
...
fac = lim / 20;
if (fac < 1)
fac = 1;
for (i = 0, col = 0; i < 27; i++, j++) {
col += 3;
k = 21 - (let[i] / fac);
star = (let[i] == 0) ? ' ' : '*';
for (j = k; j < 22; j++)
draw(j, col, star);
}
draw(23, 2, ' ');
for (i = 'A'; i <= 'Z'; i++)
printf("%c ", i);
Код включает, среди прочего, числа 20, 21, 22, 23 и 27. Они явно связаны ... или они?На самом деле, для этой программы есть только три числа: 24 - количество строк на экране;80 - количество столбцов;и 26, количество букв в алфавите.Но ничего из этого не появляется в коде, что делает числа, делающие их еще более волшебными.
Присваивая имена главным числам в расчете, мы можем упростить выполнение кода.Например, мы обнаруживаем, что число 3 взято из (80 - 1) / 26, и что пусть должно содержать 26 записей, а не 27 (ошибка, возможно, вызванная 1-индексированными координатами экрана).Сделав несколько других упрощений, это результат:
enum {
MINROW = 1, /* top row */
MINCOL = 1, /* left edge */
MAXROW = 24, /* bottom edge (<=) */
MAXCOL = 80, /* right edge (<=) */
LABELROW = 1, /* position of labels */
NLET = 26, /* size of alphabet */
HEIGHT = (MAXROW - 4), /* height of bars */
WIDTH = (MAXCOL - 1)/NLET /* width of bars */
};
...
fac = (lim + HEIGHT - 1) / HEIGHT;
if (fac < 1)
fac = 1;
for (i = 0; i < NLET; i++) {
if (let[i] == 0)
continue;
for (j = HEIGHT - let[i]/fac; j < HEIGHT; j++)
draw(j+1 + LABELROW, (i+1)*WIDTH, '*');
}
draw(MAXROW-1, MINCOL+1, ' ');
for (i = 'A'; i <= 'Z'; i++)
printf("%c ", i);
Теперь стало понятнее, что делает основной цикл;это идиоматический цикл от 0 до NLET, указывающий, что цикл находится над элементами данных.Также вызовы draw
легче понять, потому что такие слова, как MAXROW и MINCOL, напоминают нам о порядке аргументов.Самое главное, что теперь возможно адаптировать программу к другому размеру дисплея или другим данным.Числа демистифицированы, как и код.
Пересмотренный код на самом деле не использует MINROW, что интересно;Интересно, какой из оставшихся 1 должен быть МИНРОУ.