ISO/IEC JTC1/SC22/WG14 N3922 2026-07-12
Jakub Jelínek, jakub@redhat.com
Abstract
ChangeLog
Revision 0
Introduction and Motivation
Wording
Acknowledgments
This paper proposes dropping some restrictions on use of
bit-precise integer types in stdbit.h type-generic macros.
— Initial release.
C23 introduced bit-precise integer types, however various restrictions
on stdbit.h type-generic macros make the bit-precise integer
types second class citizens.
The usual wording is: a bit-precise unsigned integer type whose width
matches a standard or extended integer type.
If a C23 or C2Y implementation implements the bare minimum bit-precise
integer types (so e.g. with BITINT_MAXWIDTH equal to
LLONG_WIDTH or perhaps twice as big value), modifying
all of the stdbit.h type-generic macros to also support
arbitrary supported bit-precise integer types is fairly easy. In
some cases it is just a matter of zero-extending the value into
the largest standard or extended integer type, in other cases one
needs to query the width of the bit-precise integer type (can be done
using _Generic or e.g. using stdc_count_ones
on (unsigned long long) ~(typeof (value))0)
and combine that with the result of the type-generic macro on
a larger standard or extended integer type. Or, if it is twice the
size of the largest standard or extended integer type, it can be often
implemented using the type-generic macro on both the low and high
halves of the value cast to the largest standard or extended integer type.
If an implementation already supports much larger values of
BITINT_MAXWIDTH, then significant effort has already
been spent to implement arithmetics, cast from/to floating point types
(including decimal floating point) and implementing extra type-generic
intrinsics for the stdbit.h type-generic macros is just
a very small fraction of the overall engineering effort to implement
bit-precise integer types.
Both GCC and Clang implement various built-in functions which can be
used to implement stdbit.h macros, e.g.
__builtin_clzg, __builtin_ctzg, __builtin_clrsbg,
__builtin_ffsg, __builtin_parityg, __builtin_popcountg,
__builtin_bswapg, __builtin_bitreverseg,
and
__builtin_stdc_bit_ceil, __builtin_stdc_bit_floor,
__builtin_stdc_bit_width, __builtin_stdc_count_ones,
__builtin_stdc_count_zeros, __builtin_stdc_first_leading_one,
__builtin_stdc_first_leading_zero, __builtin_stdc_first_trailing_one,
__builtin_stdc_first_trailing_zero, __builtin_stdc_has_single_bit,
__builtin_stdc_leading_ones, __builtin_stdc_leading_zeros,
__builtin_stdc_rotate_left, __builtin_stdc_rotate_right,
__builtin_stdc_trailing_ones,
__builtin_stdc_trailing_zeros.
With these, e.g. the GNU C library supports in stdbit.h
arbitrary bit-precise integer types without too much extra effort.
If width of bit-precise unsigned integer needs to be determined amd
BITINT_MAXWIDTH is large, one possibility is using
__builtin_popcountg(~(typeof(val))0), another one
provided the largest known ABI limb width is e.g. 128 is to use
_Generic with associations for bit-precise integers with width
from 1 to 127 and then sizeof(val)*CHAR_BIT,
sizeof(val)*CHAR_BIT-1 down to
sizeof(val)*CHAR_BIT-127 guarded so that it is never
larger than BITINT_MAXWIDTH and finally if needed some
widths near BITINT_MAXWIDTH.
The wording is relative to the latest Working Draft at time of publication, N3886.
Modify 7.18.3 Count Leading Zeros paragraph 2:
Returns the number of consecutive 0 bits in value, starting from the most significant bit.
The type-generic functionstdc_leading_zerosreturns the appropriate value based on the type of the input value, provided that it is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.4 Count Leading Ones paragraph 2:
Returns the number of consecutive 1 bits in value, starting from the most significant bit.
The type-generic functionstdc_leading_onesreturns the appropriate value based on the type of the input value, provided that it is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.5 Count Trailing Zeros paragraph 2:
Returns the number of consecutive 0 bits in value, starting from the least significant bit.
The type-generic functionstdc_trailing_zerosreturns the appropriate value based on the type of the input value, provided that it is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.6 Count Trailing Ones paragraph 2:
Returns the number of consecutive 1 bits in value, starting from the least significant bit.
The type-generic functionstdc_trailing_onesreturns the appropriate value based on the type of the input value, provided that it is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.7 First Leading Zero paragraph 2:
Returns the most significant index of the first 0 bit in value, plus 1. If it is not found, this function returns 0.
The type-generic functionstdc_first_leading_zeroreturns the appropriate value based on the type of the input value, provided that it is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.8 First Leading One paragraph 2:
Returns the most significant index of the first 1 bit in value, plus 1. If it is not found, this function returns 0.
The type-generic functionstdc_first_leading_onereturns the appropriate value based on the type of the input value, provided that it is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.9 First Trailing Zero paragraph 2:
Returns the least significant index of the first 0 bit in value, plus 1. If it is not found, this function returns 0.
The type-generic functionstdc_first_trailing_zeroreturns the appropriate value based on the type of the input value, provided that it is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.10 First Trailing One paragraph 2:
Returns the least significant index of the first 1 bit in value, plus 1. If it is not found, this function returns 0.
The type-generic functionstdc_first_trailing_onereturns the appropriate value based on the type of the input value, provided that it is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.11 Count Zeros paragraph 3:
The type-generic function
stdc_count_zerosreturns the previously described result for a given input value provided that the type of the generic_value_type argument is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.12 Count Ones paragraph 2:
Returns the total number of 1 bits within the given value.
The type-generic functionstdc_count_onesreturns the previously described result for a given input value the generic_value_type is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.13 Single-bit Check paragraph 2:
The
stdc_has_single_bitfunctions returntrueif and only if there is a single 1 bit in value.
The type-generic functionstdc_has_single_bitreturns the previously described result for a given input value provided that the type of the generic_value_type argument is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
Modify 7.18.14 Bit Width paragraph 3:
The
stdc_bit_widthfunctions return 0 if value is 0. Otherwise, they return1 + ⌊log2 (value)⌋.
The type-generic functionstdc_bit_widthreturns the previously described result for a given input value provided that the type of the generic_value_type argument is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
The generic_return_type type shall be a suitably large unsigned integer type capable of representing the computed result.
Modify 7.18.15 Bit Floor paragraph 3:
The
stdc_bit_floorfunctions return 0 if value is 0. Otherwise, they return the largest integral power of 2 that is not greater than value.
The type-generic functionstdc_bit_floorreturns the previously described result for a given input value the generic_value_type is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
Modify 7.18.16 Bit Ceiling paragraph 3:
The
stdc_bit_ceilfunctions return the smallest integral power of 2 that is not less than value or 0 if such a value is not representable in the return type.
The type-generic functionstdc_bit_ceilreturns the previously described result for a given input value provided that the type of the generic_value_type argument is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches a standard or extended integer type
Modify 7.18.17 Rotate Left paragraph 5:
The type-generic function
stdc_rotate_leftreturns the above described result for a given input value provided that the type of the generic_value_type argument is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches any standard or extended integer type
The count argument to the type-generic functionstdc_rotate_leftshall be a value of signed or unsigned integer type, orchar.
Modify 7.18.18 Rotate Right paragraph 5:
The type-generic function
stdc_rotate_rightreturns the above described result for a given input value provided that the type of the generic_value_type argument is:an unsigned integer type.
— a standard unsigned integer type;
— an extended unsigned integer type; or,
— a bit-precise unsigned integer type whose width matches any standard or extended integer type
The count argument to the type-generic functionstdc_rotate_rightshall be a value of signed or unsigned integer type, orchar.
Many thanks to Joseph S. Myers, Martin Uecker and Aaron Ballman.