Когда дело доходит до размеров массива, я подозреваю, что есть две причины, почему предпочтение отдается двум степеням. Один из них, о чем свидетельствуют несколько ответов, заключается в том, что программисты, которые не знают, что происходит «под капотом», как представляется, имеют общее представление о том, что может быть более эффективно использовать степень двойки. Другой (в основном исторический сейчас) связан с циклическими буферами.
Циклические буферы, имеющие степень двойки, могут обрабатываться легче и быстрее, используя маски для индексов чтения или записи (или указатели), вместо использования обычно более медленной операции по модулю или использования условий, которые требуют ветвлений. Это было важно на старых машинах, но все еще может быть важно для передачи больших объемов данных - например, обработка графики
Например, в C число байтов, доступных для чтения в циклическом буфере, может быть получено с помощью:
pending = (SIZE + wr - rd) & (SIZE - 1);
Если не использовать степень двойки, эквивалент будет:
pending = (SIZE + wr - rd) % (SIZE - 1);
На машинах, которые не реализуют инструкцию деления / модуля, этот маленький "%" может занять несколько сотен циклов, поэтому вам потребуется что-то вроде:
if (wr >= rd)
pending = wr - rd;
else
pending = (SIZE + wr) - rd;
Который загромождает код и вызывает ветвление, которое может остановить конвейер команд.
Запись в буфер, который был что-то вроде
buf[wr++] = x;
if (wr == SIZE)
rd = 0;
становится (в целом) более эффективным:
buf[wr++] = x;
wr &= SIZE-1;
Конечно, если вы использовали 8-битную переменную без знака для индексации массива из 256 записей, вам даже не нужно было выполнять маскирование.