<stdbit.h>
Bit-Related FunctionsThis header file and all the included functions are new in C23!
Caveat: none of my compilers support this, so all the code is untested!
Function | Description |
---|---|
stdc_bit_ceil() |
Return the smallest power of 2 not less than a number |
stdc_bit_floor() |
Return the largest power of 2 not greater than a number |
stdc_bit_width() |
Return the number of bits needed to store a value |
stdc_count_ones() |
Count the ones in an unsigned number |
stdc_count_zeros() |
Count the zeros in an unsigned number |
stdc_first_leading_one() |
Find the first leading one in an unsigned number |
stdc_first_leading_zero() |
Find the first leading zero in an unsigned number |
stdc_first_trailing_one() |
Find the first trailing one in an unsigned number |
stdc_first_trailing_zero() |
Find the first trailing zero in an unsigned number |
stdc_has_single_bit() |
Test to see if an unsigned integer has only a single bit set |
stdc_leading_ones() |
Count the leading ones in an unsigned number |
stdc_leading_zeros() |
Count the leading zeros in an unsigned number |
stdc_trailing_ones() |
Count the trailing ones in an unsigned number |
stdc_trailing_zeros() |
Count the trailing zeros in an unsigned number |
Since this is a new feature, you can test for its existence by making sure the __STDC_VERSION_STDBIT_H__
macro exists and is 202311L
or greater.
This header file defines a number of macros that can be used to determine the endianess of the system. (That is, in a multibyte value, do the first byte represent the most significant part of the value, or least? Or neither?)
There are two different values for the defined endianesses __STDC_ENDIAN_BIG__
and __STDC_ENDIAN_LITTLE__
.
Additionally, there’s a macro __STDC_ENDIAN_NATIVE__
that gives you the endianess of this system. You can compare that against the other two macros to see what you’ve got. If it doesn’t compare equal to either of them, you must be on some other mixed-endian system.
Let’s see what this system is:
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
switch(__STDC_ENDIAN_NATIVE__) {
case __STDC_ENDIAN_BIG__:
("Big-endian!");
putsbreak;
case __STDC_ENDIAN_LITTLE__:
("Little-endian!");
putsbreak;
default:
("Other-endian!");
puts}
}
All the functions in this header follow a standard pattern, so we might as well go over it once here up-front to save extraneous and excessive verbosity later.
Each function comes in six amazing forms, depending on the types involved.
First of all, they’re just going to operate on unsigned integer types, so we’ll get that out of the way.
And they’re mostly going to return unsigned int
.
And they come in two subforms: the type-specific and type-generic forms.
Let’s look at the type specific forms first. We’ll use the function that counts the leading zero bits in a value as an example. Here it is:
unsigned int stdc_leading_zeros_uc(unsigned char value);
unsigned int stdc_leading_zeros_us(unsigned short value);
unsigned int stdc_leading_zeros_ui(unsigned int value);
unsigned int stdc_leading_zeros_ul(unsigned long value);
unsigned int stdc_leading_zeros_ull(unsigned long long value);
Yikes. OK, what do we have?
Well, in order to prevent namespace pollution, they all start with stdc_
.
And what about this uc
, us
, ull
, etc. stuff? Those correspond to the type of the argument, you’ll see with a little inspection.
Suffix | Parameter Type |
---|---|
_uc |
unsigned char |
_us |
unsigned short |
_ui |
unsigned int |
_ul |
unsigned long |
_ull |
unsigned long long |
But wait! There’s more!
Each of these function families in the header also has a generic variant.
So, again with count_leading_zeros
as an example, there’s a version that doesn’t need types to be specified, and it’s just the function without any suffix.
(generic_value_type value); generic_return_type stdc_leading_zeros
In that example, the words generic_return_type
and generic_value_type
are not C keywords. They’re just placeholders to let you know you need to put the right thing there.
unsigned short x = 3490;
unsigned int a = stdc_leading_zeros(x);
auto b = stdc_leading_zeros(1234);
The generic functions work with all unsigned types, not counting bool
.
stdc_leading_zeros()
Count the leading zeros in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_leading_zeros_uc(unsigned char value);
unsigned int stdc_leading_zeros_us(unsigned short value);
unsigned int stdc_leading_zeros_ui(unsigned int value);
unsigned int stdc_leading_zeros_ul(unsigned long value);
unsigned int stdc_leading_zeros_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_leading_zeros
This function returns the number of leading zero bits on a particular value, starting from the most-significant bit. The number will be influenced by the size of the argument.
Returns the number of leading zero bits.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 3490;
unsigned int count = stdc_leading_zeros_ui(value);
printf("%u\n", count);
unsigned long long value2 = 3490;
auto count2 = stdc_leading_zeros(value2);
printf("%u\n", count2);
}
stdc_leading_ones()
, stdc_trailing_zeros()
stdc_leading_ones()
Count the leading ones in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_leading_ones_uc(unsigned char value);
unsigned int stdc_leading_ones_us(unsigned short value);
unsigned int stdc_leading_ones_ui(unsigned int value);
unsigned int stdc_leading_ones_ul(unsigned long value);
unsigned int stdc_leading_ones_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_leading_ones
This function returns the number of leading one bits on a particular value starting from the most-significant bit. The number will be influenced by the size of the argument.
Returns the number of leading one bits.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 3490;
unsigned int count = stdc_leading_ones_ui(value);
printf("%u\n", count);
unsigned long long value2 = 3490;
auto count2 = stdc_leading_ones(value2);
printf("%u\n", count2);
}
stdc_leading_zeros()
, stdc_trailing_ones()
stdc_trailing_zeros()
Count the trailing zeros in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_trailing_zeros_uc(unsigned char value);
unsigned int stdc_trailing_zeros_us(unsigned short value);
unsigned int stdc_trailing_zeros_ui(unsigned int value);
unsigned int stdc_trailing_zeros_ul(unsigned long value);
unsigned int stdc_trailing_zeros_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_trailing_zeros
This function returns the number of trailing zero bits on a particular value, starting from the least-significant bit. The number will be influenced by the size of the argument.
Returns the number of trailing zero bits.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 3490;
unsigned int count = stdc_trailing_zeros_ui(value);
printf("%u\n", count);
unsigned long long value2 = 3490;
auto count2 = stdc_trailing_zeros(value2);
printf("%u\n", count2);
}
stdc_trailing_ones()
, stdc_leading_zeros()
stdc_trailing_ones()
Count the trailing ones in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_trailing_ones_uc(unsigned char value);
unsigned int stdc_trailing_ones_us(unsigned short value);
unsigned int stdc_trailing_ones_ui(unsigned int value);
unsigned int stdc_trailing_ones_ul(unsigned long value);
unsigned int stdc_trailing_ones_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_trailing_ones
This function returns the number of trailing one bits on a particular value, starting from the least-significant bit. The number will be influenced by the size of the argument.
Returns the number of trailing one bits.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 3490;
unsigned int count = stdc_trailing_ones_ui(value);
printf("%u\n", count);
unsigned long long value2 = 3490;
auto count2 = stdc_trailing_ones(value2);
printf("%u\n", count2);
}
stdc_trailing_zeros()
, stdc_leading_ones()
stdc_first_leading_zero()
Find the first leading zero in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_first_leading_zero_uc(unsigned char value);
unsigned int stdc_first_leading_zero_us(unsigned short value);
unsigned int stdc_first_leading_zero_ui(unsigned int value);
unsigned int stdc_first_leading_zero_ul(unsigned long value);
unsigned int stdc_first_leading_zero_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_first_leading_zero
This finds the index of the first leading zero in a number. Indexes are numbered starting from 1
being the most significant (“leftmost”) bit position. (This might be in contrast to how you might be used to numbering bit indexes.)
It’s one-based so that you can quickly use the return value as a Boolean expression for if it found a zero bit or not.
Returns the 1-based index from the most significant bit of the first zero bit in the value
, or 0
if there are no zero bits.
#include <stdio.h>
#include <limits.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = UINT_MAX;
unsigned int index = stdc_first_leading_zero_ui(value);
printf("%u\n", index);
unsigned long long value2 = UINT_MAX >> 2;
auto index2 = stdc_first_leading_zero(value2);
printf("%u\n", index2);
}
stdc_first_leading_one()
, stdc_first_trailing_zero()
stdc_first_leading_one()
Find the first leading one in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_first_leading_one_uc(unsigned char value);
unsigned int stdc_first_leading_one_us(unsigned short value);
unsigned int stdc_first_leading_one_ui(unsigned int value);
unsigned int stdc_first_leading_one_ul(unsigned long value);
unsigned int stdc_first_leading_one_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_first_leading_one
This finds the index of the first leading one in a number. Indexes are numbered starting from 1
being the most significant (“leftmost”) bit position. (This might be in contrast to how you might be used to numbering bit indexes.)
It’s one-based so that you can quickly use the return value as a Boolean expression for if it found a one bit or not.
Returns the 1-based index from the most significant bit of the first one bit in the value
, or 0
if there are no one bits.
#include <stdio.h>
#include <limits.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = UINT_MAX;
unsigned int index = stdc_first_leading_one_ui(value);
printf("%u\n", index);
unsigned long long value2 = UINT_MAX >> 2;
auto index2 = stdc_first_leading_one(value2);
printf("%u\n", index2);
}
stdc_first_leading_zero()
, stdc_first_trailing_one()
stdc_first_trailing_zero()
Find the first trailing zero in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_first_trailing_zero_uc(unsigned char value);
unsigned int stdc_first_trailing_zero_us(unsigned short value);
unsigned int stdc_first_trailing_zero_ui(unsigned int value);
unsigned int stdc_first_trailing_zero_ul(unsigned long value);
unsigned int stdc_first_trailing_zero_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_first_trailing_zero
This finds the index of the first trailing zero in a number. Indexes are numbered starting from 1
being the most significant (“leftmost”) bit position. (This might be in contrast to how you might be used to numbering bit indexes.)
It’s one-based so that you can quickly use the return value as a Boolean expression for if it found a zero bit or not.
Returns the 1-based index from the most significant bit of the first zero bit in the value
, or 0
if there are no zero bits.
#include <stdio.h>
#include <limits.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = UINT_MAX;
unsigned int index = stdc_first_trailing_zero_ui(value);
printf("%u\n", index);
unsigned long long value2 = UINT_MAX >> 2;
auto index2 = stdc_first_trailing_zero(value2);
printf("%u\n", index2);
}
stdc_first_leading_zero()
, stdc_first_trailing_one()
stdc_first_trailing_one()
Find the first trailing one in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_first_trailing_one_uc(unsigned char value);
unsigned int stdc_first_trailing_one_us(unsigned short value);
unsigned int stdc_first_trailing_one_ui(unsigned int value);
unsigned int stdc_first_trailing_one_ul(unsigned long value);
unsigned int stdc_first_trailing_one_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_first_trailing_one
This finds the index of the first trailing one in a number. Indexes are numbered starting from 1
being the most significant (“leftmost”) bit position. (This might be in contrast to how you might be used to numbering bit indexes.)
It’s one-based so that you can quickly use the return value as a Boolean expression for if it found a one bit or not.
Returns the 1-based index from the most significant bit of the first one bit in the value
, or 0
if there are no one bits.
#include <stdio.h>
#include <limits.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = UINT_MAX;
unsigned int index = stdc_first_trailing_one_ui(value);
printf("%u\n", index);
unsigned long long value2 = UINT_MAX >> 2;
auto index2 = stdc_first_trailing_one(value2);
printf("%u\n", index2);
}
stdc_first_leading_one()
, stdc_first_trailing_zero()
stdc_count_zeros()
Count the zeros in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_count_zeros_uc(unsigned char value);
unsigned int stdc_count_zeros_us(unsigned short value);
unsigned int stdc_count_zeros_ui(unsigned int value);
unsigned int stdc_count_zeros_ul(unsigned long value);
unsigned int stdc_count_zeros_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_count_zeros
This function returns the number of zero bits in a particular value. The number will be influenced by the size of the argument.
Returns the number of zero bits.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 3490;
unsigned int count = stdc_count_zeros_ui(value);
printf("%u\n", count);
unsigned long long value2 = 123456;
auto count2 = stdc_count_zeros(value2);
printf("%u\n", count2);
}
stdc_count_ones()()
, stdc_leading_zeros()()
, stdc_trailing_zeros()()
stdc_count_ones()
Count the ones in an unsigned number
New in C23!
#include <stdbit.h>
unsigned int stdc_count_ones_uc(unsigned char value);
unsigned int stdc_count_ones_us(unsigned short value);
unsigned int stdc_count_ones_ui(unsigned int value);
unsigned int stdc_count_ones_ul(unsigned long value);
unsigned int stdc_count_ones_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_count_ones
This function returns the number of one bits in a particular value. The number will be influenced by the size of the argument.
Returns the number of one bits.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 3490;
unsigned int count = stdc_count_ones_ui(value);
printf("%u\n", count);
unsigned long long value2 = 123456;
auto count2 = stdc_count_ones(value2);
printf("%u\n", count2);
}
stdc_count_zeros()()
, stdc_leading_ones()()
, stdc_trailing_ones()()
stdc_has_single_bit()
Test to see if an unsigned integer has only a single bit set
New in C23!
#include <stdbit.h>
bool stdc_has_single_bit_uc(unsigned char value);
bool stdc_has_single_bit_us(unsigned short value);
bool stdc_has_single_bit_ui(unsigned int value);
bool stdc_has_single_bit_ul(unsigned long value);
bool stdc_has_single_bit_ull(unsigned long long value);
bool stdc_has_single_bit(generic_value_type value);
These functions return true if exactly one bit is 1
in an unsigned value
.
If true, it also means the value
is a power of 2.
Return true if value
has exactly a single bit set to 1
.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 0b0001000;
unsigned int result = stdc_has_single_bit_ui(value);
printf("%d\n", result); // 1
unsigned long long value2 = 0b000011000
auto result2 = stdc_has_single_bit(value2);
printf("%d\n", result2); // 0
}
stdc_bit_width()
Return the number of bits needed to store a value
New in C23!
#include <stdbit.h>
unsigned int stdc_bit_width_uc(unsigned char value);
unsigned int stdc_bit_width_us(unsigned short value);
unsigned int stdc_bit_width_ui(unsigned int value);
unsigned int stdc_bit_width_ul(unsigned long value);
unsigned int stdc_bit_width_ull(unsigned long long value);
(generic_value_type value); generic_return_type stdc_bit_width
Given an unsigned integer value, what’s the smallest number of bits needed to store it? That’s the question this function answers.
Returns the number of bits needed to store a positive value
. Returns 0
if the value
passed in is 0
.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 0b0001000;
unsigned int result = stdc_bit_width_ui(value);
printf("%d\n", result); // 4
unsigned long long value2 = 0b000011010
auto result2 = stdc_bit_width(value2);
printf("%d\n", result2); // 5
}
stdc_bit_floor()
Return the largest power of 2 not greater than a number
New in C23!
#include <stdbit.h>
unsigned char stdc_bit_floor_uc(unsigned char value);
unsigned short stdc_bit_floor_us(unsigned short value);
unsigned int stdc_bit_floor_ui(unsigned int value);
unsigned long stdc_bit_floor_ul(unsigned long value);
unsigned long long stdc_bit_floor_ull(unsigned long long value);
(generic_value_type value); generic_value_type stdc_bit_floor
This function returns the largest power of 2 that is not greater than the value
.
In other words “is less than or equal to” the value
.
In other words, floor down to the nearest power of two.
In other words, return the value of the highest set bit in a number
For example: |value
|Return| |-|-| |0b101
|0b100
| |0b1000
|0b1000
| |0b100101
|0b100000
|
Returns the largest power of 2 not greater than value
. Returns 0
if the value
is 0
.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 0b0001000;
unsigned int result = stdc_bit_floor_ui(value);
printf("%b\n", result); // 1000
unsigned long long value2 = 0b000011010
auto result2 = stdc_bit_floor(value2);
printf("%b\n", result2); // 10000
}
stdc_bit_ceil()
Return the smallest power of 2 not less than a number
New in C23!
#include <stdbit.h>
unsigned char stdc_bit_ceil_uc(unsigned char value);
unsigned short stdc_bit_ceil_us(unsigned short value);
unsigned int stdc_bit_ceil_ui(unsigned int value);
unsigned long stdc_bit_ceil_ul(unsigned long value);
unsigned long long stdc_bit_ceil_ull(unsigned long long value);
(generic_value_type value); generic_value_type stdc_bit_ceil
This function returns the smallest power of 2 that is not less than the value
.
In other words “is greater than or equal to” the value
.
In other words, ceil up to the nearest power of two.
For example: |value
|Return| |-|-| |0b101
|0b1000
| |0b1000
|0b1000
| |0b100101
|0b1000000
|
If the result doesn’t fit in the return type, the behavior is undefined.
Returns the smallest power of 2 not less than value
.
#include <stdio.h>
#include <stdbit.h>
int main(void)
{
unsigned int value = 0b0001000;
unsigned int result = stdc_bit_ceil_ui(value);
printf("%b\n", result); // 1000
unsigned long long value2 = 0b000011010
auto result2 = stdc_bit_ceil(value2);
printf("%b\n", result2); // 100000
}