The C23 <stdbit.h> header provides type-generic macros for inspecting and manipulating bits in unsigned integer values. Its descriptive operations express properties directly: stdc_count_ones counts set bits, stdc_has_single_bit tests for a singleton, stdc_bit_width reports the highest occupied bit position plus one, and stdc_bit_floor returns the highest-power-of-two singleton not exceeding the argument. section 5.7.2 section 8.2
Inspecting an unsigned value
#include <stdbool.h> #include <stdio.h> #include <stdbit.h> int main(void) { unsigned x = 0x2Cu; printf("ones: %u\n", stdc_count_ones(x)); printf("single bit: %s\n", stdc_has_single_bit(x) ? "yes" : "no"); printf("width: %u\n", stdc_bit_width(x)); printf("floor: 0x%X\n", stdc_bit_floor(x)); } These operations avoid spelling out shifts, masks, and exceptional-case branches. Their results are defined for every argument value, including zero and values that exercise boundary cases. section 5.7.2 section 8.2
Use the header with these portability and readability rules:
- Prefer descriptive property-based operations when their meaning matches the task; reserve magnitude or complement variants for cases where their exceptional results are specifically wanted. section 8.2
- Check availability before requiring the header, because a platform may not yet implement this C23 facility. section 5.7.2
- Keep bitwise operators distinct from && and ||: &, |, and related operators process bit patterns, while logical operators use short-circuit evaluation. section 5.7.2
Table 8.5 Functions for integer arithmetic. Most of these are type-generic macros, but some also have function interfaces for specific types. \(x\) and \(y\) denote the arguments, \(\overline{x}\) is a bitwise complement, \(w\) the width, and \(m\) the maximum value of the type.
| Function | Description | Remark |
abs, labs, llabs |
\(|x|\) | Type independent |
div, ldiv, lldiv |
\(x\)/\(y\) and \(x\)%\(y\) |
Type independent |
ckd_add |
\(x\)+\(y\) (LS bits) & overflow flag |
Target dependent |
ckd_mul |
\(x\)*\(y\) (LS bits) & overflow flag |
Target dependent |
ckd_sub |
\(x\)-\(y\) (LS bits) & overflow flag |
Target dependent |
stdc_bit_ceil |
\(2^{\lceil \log_2 x\rceil}\) | \(1\) if \(x \equiv 0\), \(0\) if \(x > m/2\) |
stdc_bit_floor |
\(2^{\lfloor \log_2 x\rfloor}\) | \(0\) if \(x \equiv 0\) |
stdc_bit_width |
\(1 + {\lfloor \log_2 x\rfloor}\) | \(0\) if \(x \equiv 0\) |
stdc_count_ones |
Number of \(1\)-bits in \(x\) | Type independent |
stdc_count_zeros |
Number of \(1\)-bits in \(\overline{x}\) | Type dependent |
stdc_has_single_bit |
There is 𝑁 with \(x \equiv 2^n\) | Type independent |
stdc_first_leading_one |
\(w - {\big\lfloor \log_2 x\big\rfloor}\) | \(0\) if \(x \equiv 0\) |
stdc_first_leading_zero |
\(w - {\big\lfloor \log_2 \overline{x}\big\rfloor}\) | \(0\) if \(x\) has all bits set |
stdc_leading_ones |
\(w - {\big\lfloor \log_2 \overline{x}\big\rfloor} - 1\) | \(w\) if \(x \equiv 0\) |
stdc_leading_zeros |
\(w - {\big\lfloor \log_2 x\big\rfloor} - 1\) | \(w\) if \(x \equiv 0\) |
stdc_first_trailing_one |
One plus LS \(1\)-bit in \(x\) | \(0\) if \(x \equiv 0\) |
stdc_first_trailing_zero |
One plus LS \(0\)-bit in \(x\) | \(0\) if \(x \equiv 0\) |
stdc_trailing_ones |
One plus LS \(0\)-bit in \(x\) | \(w\) if \(x \equiv 0\) |
stdc_trailing_zeros |
One plus LS \(1\)-bit in \(x\) | \(w\) if \(x \equiv 0\) |
Use the function table to compare stdc_bit_floor, stdc_bit_width, stdc_count_ones, and related operations, including their zero and boundary-case results. section 8.2
