Для 32-разрядных целых чисел это простой и понятный маршрут:
unsigned int n;
n--;
n |= n >> 1; // Divide by 2^k for consecutive doublings of k up to 32,
n |= n >> 2; // and then or the results.
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
n++; // The result is a number of 1 bits equal to the number
// of bits in the original number, plus 1. That's the
// next highest power of 2.
Вот более конкретный пример. Давайте возьмем число 221, которое является 11011101 в двоичном виде:
n--; // 1101 1101 --> 1101 1100
n |= n >> 1; // 1101 1100 | 0110 1110 = 1111 1110
n |= n >> 2; // 1111 1110 | 0011 1111 = 1111 1111
n |= n >> 4; // ...
n |= n >> 8;
n |= n >> 16; // 1111 1111 | 1111 1111 = 1111 1111
n++; // 1111 1111 --> 1 0000 0000
В девятой позиции есть один бит, который представляет 2 ^ 8 или 256, что на самом деле является следующей по величине степенью 2 . Каждое из сдвигов перекрывает все существующие 1 бит в числе с некоторыми из ранее нетронутых нулей, в конечном итоге получая число 1 бит, равное количеству бит в исходном числе. Добавление одного к этому значению дает новую степень 2.
Другой пример; мы будем использовать 131, который равен 10000011 в двоичном виде:
n--; // 1000 0011 --> 1000 0010
n |= n >> 1; // 1000 0010 | 0100 0001 = 1100 0011
n |= n >> 2; // 1100 0011 | 0011 0000 = 1111 0011
n |= n >> 4; // 1111 0011 | 0000 1111 = 1111 1111
n |= n >> 8; // ... (At this point all bits are 1, so further bitwise-or
n |= n >> 16; // operations produce no effect.)
n++; // 1111 1111 --> 1 0000 0000
И действительно, 256 - это следующая по величине степень 2 из 131.
Если число битов, используемых для представления целого числа, само является степенью 2, вы можете продолжать расширять этот метод эффективно и неограниченно (например, добавьте строку n >> 32
для 64-битных целых чисел).