C23 stdbit.h quick reference
| Macros | Implementation |
|---|---|
#define __STDC_ENDIAN_LITTLE__ | Some integer constant |
#define __STDC_ENDIAN_BIG__ | Some integer constant |
#define __STDC_ENDIAN_NATIVE__ | __STDC_ENDIAN_LITTLE__ or__STDC_ENDIAN_BIG__ (†) |
| Regular functions | Implementation |
unsigned stdc_leading_zeros(T x) | lzcnt(x) |
unsigned stdc_first_leading_one(T x) | x ? lzcnt(x) + 1 : 0 |
unsigned stdc_trailing_zeros(T x) | tzcnt(x) |
unsigned stdc_first_trailing_one(T x) | x ? tzcnt(x) + 1 : 0 |
unsigned stdc_count_ones(T x) | popcnt(x) |
bool stdc_has_single_bit(T x) | popcnt(x) == 1 |
unsigned stdc_bit_width(T x) | x ? floor(log2(x)) + 1 : 0 |
T stdc_bit_floor(T x) | x ? (T)1 << floor(log2(x)) : 0 |
T stdc_bit_ceil(T x) | x ? (T)1 << ceil(log2(x)) : 1 (‡) |
| Inverted functions | Implementation |
unsigned stdc_leading_ones(T x) | lzcnt((T)~x) |
unsigned stdc_first_leading_zero(T x) | (T)~x ? lzcnt((T)~x) + 1 : 0 |
unsigned stdc_trailing_ones(T x) | tzcnt((T)~x) |
unsigned stdc_first_trailing_zero(T x) | (T)~x ? tzcnt((T)~x) + 1 : 0 |
unsigned stdc_count_zeros(T x) | popcnt((T)~x) |
(†) Or some third value if the execution environment is neither little endian nor big endian.
(‡) Undefined if the << overflows or if the result does not fit in T.
Where:
Tdenotes eitherunsigned charorunsigned shortorunsigned intorunsigned longorunsigned long long. Each function takingTis type-generic, dispatching to one of these five variants. The individual variants are also available by appending a_ucor_usor_uior_ulor_ullsuffix to the function name. Implementations might also supportuint128_t.lzcntreturns the number of leading zero bits. For an input of zero, this issizeof(T) * CHAR_BIT.tzcntreturns the number of trailing zero bits. For an input of zero, this issizeof(T) * CHAR_BIT.popcntreturns the number of set bits. For an input with all bits set, this issizeof(T) * CHAR_BIT.log2(0)is undefined,log2coincides withtzcntfor inputs that are powers of two, and otherwiselog2is strictly monotonic and returns a float.
The inverted functions can all be implemented by inverting the input and then passing it to one of the regular functions.
The stdc_first_leading_ functions are slightly slippery, and require a careful reading of the standard. For example, stdc_first_leading_one is defined as:
Returns the most significant index of the first 1 bit in
value, plus 1. If it is not found, this function returns0.
In turn, most significant index has the following unintuitive definition:
The most significant index is the
0-based index counting from the most significant bit,0, to the least significant bit,w − 1, wherewis the width of the type that is having its most significant index computed.
The initial patches for these functions in musl got this wrong, instead using the more intuitive definition of most significant index. The VLC compat header also got this wrong, twice.