c99 has given us log2
. This removes the need for all the special sauce log2
implementations you see on this page. You can use the standard's log2
implementation like this:
const auto n = 13UL;const auto Index = (unsigned long)log2(n);printf("MSB is: %u\n", Index); // Prints 3 (zero offset)
An n
of 0UL
needs to be guarded against as well, because:
-∞ is returned and FE_DIVBYZERO is raised
I have written an example with that check that arbitrarily sets Index
to ULONG_MAX
here: https://ideone.com/u26vsi
The visual-studio corollary to ephemient's gcc only answer is:
const auto n = 13UL;unsigned long Index;_BitScanReverse(&Index, n);printf("MSB is: %u\n", Index); // Prints 3 (zero offset)
The documentation for _BitScanReverse
states that Index
is:
Loaded with the bit position of the first set bit (1) found
In practice I've found that if n
is 0UL
that Index
is set to 0UL
, just as it would be for an n
of 1UL
. But the only thing guaranteed in the documentation in the case of an n
of 0UL
is that the return is:
0 if no set bits were found
Thus, similarly to the preferable log2
implementation above the return should be checked setting Index
to a flagged value in this case. I've again written an example of using ULONG_MAX
for this flag value here: http://rextester.com/GCU61409