if anyone knows a way to count the number of bits in uintmax_t
, that'd be perfect, but failing that where have I got INT64_TYPE from?
To count the number of bit in an unsigned type is easy. Set to -1 and count the number of shift until 0.
int bc_uintmax_t(void) {
int bc = 0;
uintmax_t x = -1;
while (x) {
x %= 2;
bc++;
}
return bc;
}
To portable detect the number of bits in uintmax_t
at compile time is harder. A chief obstacle is the pre-preprocessor arithmetic may only work up to intmax_t
. So unless some assumptions are made, a portable solution may be unfindable.
Of course sizeof (uintmax_t) * CHAR_BIT
is the maximum possible bit width that type could have. Yet padding bits could occur.
Look for (u)intmax_t
and Exact-width integer types like uint64_t
in <stdint.h>
.
[Edit]
To determine the value bit width of a constant at compile time, code could use the following. Note: With UINTMAX_MAX
, I am not certain how portable is this code.
#include <stdio.h>
#include <limits.h>
#define ISGE2_1(x) ((x) >= 2)
#define ISGE2_2(x) ((x) >= 4)
#define ISGE2_4(x) ((x) >= 16)
#define ISGE2_8(x) ((x) >= 256)
#define ISGE2_16(x) ((x) >= 65536)
#define ISGE2_32(x) ((x)/65536 >= 65536)
#define ISGE2_64(x) ((x)/4294967296 >= 4294967296)
#define ISGE2_128(x) ((x)/18446744073709551616 >= 18446744073709551616)
#define BW_1ORLESS(x) ((x) ? 1 : 0)
#define BW_2ORLESS(x) (ISGE2_1(x) ? 1 + BW_1ORLESS(x/2) : BW_1ORLESS(x))
#define BW_4ORLESS(x) (ISGE2_2(x) ? 2 + BW_2ORLESS(x/4) : BW_2ORLESS(x))
#define BW_8ORLESS(x) (ISGE2_4(x) ? 4 + BW_4ORLESS(x/16) : BW_4ORLESS(x))
#define BW_16ORLESS(x) (ISGE2_8(x) ? 8 + BW_8ORLESS(x/256) : BW_8ORLESS(x))
#define BW_32ORLESS(x) (ISGE2_16(x) ? 16 + BW_16ORLESS(x/65536) : BW_16ORLESS(x))
#define BW_64ORLESS(x) (ISGE2_32(x) ? 32 + BW_32ORLESS(x/4294967296) : BW_32ORLESS(x))
#define BW_128ORLESS(x) (ISGE2_64(x) ? 64 + BW_64ORLESS(x/18446744073709551616) : BW_64ORLESS(x))
#if INTMAX_MAX/4294967296 > 4294967296
#define BW_65PLUS(x) (ISGE2_128(x) ? BW_129PLUS(x) : BW_128ORLESS(x))
#define BIT_WIDTH_POSITIVE_VALUE(x) (ISGE2_64(x) ? BW_65PLUS(x) : BW_64ORLESS(x))
#else
#define BW_33PLUS(x) (ISGE2_64(x) ? BW_65PLUS(x) : BW_64ORLESS(x))
#define BIT_WIDTH_POSITIVE_VALUE(x) (ISGE2_32(x) ? BW_64ORLESS(x) : BW_32ORLESS(x))
#endif
// Do not call BIT_WIDTH_POSITIVE_VALUE with negative values.
Application
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
int main() {
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(true));
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(CHAR_BIT));
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(SCHAR_MAX));
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(SHRT_MAX));
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(INT_MAX));
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(LONG_MAX));
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(LLONG_MAX));
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(INTMAX_MAX));
printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(UINTMAX_MAX));
return 0;
}
Output
1
4
7
15
31
31
63
63
64