F
Frederick Gotham
Over on comp.lang.c, Hallvard B Furuseth devised a compile-time constant
representing the amount of value representation bits in an unsigned
integer type. In true C fashion, here it is as a macro:
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 3.2E+
10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL
*30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%
31+3))
You supply it with an unsigned integer value whose bit-pattern consists
of all 1's, e.g.:
1 (Decimal: 1)
11 (Decimal: 3)
111 (Decimal: 7)
11111111 (Decimal: 255)
To find out the amount of value bits in an unsigned integer type, you
supply it with that type's max value (i.e. a bit pattern of all 1's). The
handiest way to get the max value of an unsigned integer type is to
assign -1 to it:
unsigned const max_value = -1;
unsigned const amount_value_bits = IMAX_BITS( max_value );
Here's some template code I've written which makes use of it:
template<class T>
struct IMaxBits {
template<T m>
struct AllOnes {
static unsigned const val =
m /(m%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30
+ m%0x3fffffffL /(m%31+1)/31%31*5 + 4-12/(m%31+3);
};
};
template<class T>
struct AmountValueBits {
static unsigned const val = IMaxBits<T>::template AllOnes<-1>::val;
};
#include <cstdlib>
#include <cstring>
#include <cstddef>
#include <cassert>
template<std::size_t width>
inline const char* CenterHoriz( const char * const p )
{
using std::memset;
using std::strlen;
using std::size_t;
static char spaces[width + 1];
memset( spaces, ' ', width );
size_t const len = strlen( p );
assert( width >= len );
char * const pos = spaces + ( width / 2 - len / 2 );
memcpy( pos, p, len );
return spaces;
}
#include <iostream>
extern char const str_uchar[] = "unsigned char";
extern char const str_ushort[] = "unsigned short";
extern char const str_uint[] = "unsigned int";
extern char const str_ulong[] = "unsigned long";
template<class T, const char* str>
void PrintRow()
{
using std::cout;
unsigned const total_bits = sizeof(T) * AmountValueBits<unsigned
char>::val;
unsigned const val_bits = AmountValueBits<T>::val;
unsigned const pad_bits = total_bits - val_bits;
const char * const spaces_val =
val_bits > 99 ? "" : ( val_bits > 9 ? " " : " " );
const char * const spaces_pad =
pad_bits > 99 ? "" : ( pad_bits > 9 ? " " : " " );
const char * const spaces_total =
total_bits > 99 ? "" : ( total_bits > 9 ? " " : " " );
cout << "||" << CenterHoriz<21>(str) << "|| "
<< spaces_val << val_bits << " || " << spaces_pad <<
pad_bits
<< " || " << spaces_total << total_bits << " ||\n"
"---------------------------------------------------------------------
\n";
}
int main()
{
using std::cout;
cout <<
"
==============================================\n"
" || Value bits || Padding Bits || Total Bits
||\n"
"=====================================================================
\n";
PrintRow<unsigned char, str_uchar>();
PrintRow<unsigned short, str_ushort>();
PrintRow<unsigned, str_uint>();
PrintRow<unsigned long, str_ulong>();
cout << "\n\n\n";
std::system( "PAUSE" );
}
I'd be interested to hear if anyone gets some "interesting" values.
representing the amount of value representation bits in an unsigned
integer type. In true C fashion, here it is as a macro:
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 3.2E+
10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL
*30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%
31+3))
You supply it with an unsigned integer value whose bit-pattern consists
of all 1's, e.g.:
1 (Decimal: 1)
11 (Decimal: 3)
111 (Decimal: 7)
11111111 (Decimal: 255)
To find out the amount of value bits in an unsigned integer type, you
supply it with that type's max value (i.e. a bit pattern of all 1's). The
handiest way to get the max value of an unsigned integer type is to
assign -1 to it:
unsigned const max_value = -1;
unsigned const amount_value_bits = IMAX_BITS( max_value );
Here's some template code I've written which makes use of it:
template<class T>
struct IMaxBits {
template<T m>
struct AllOnes {
static unsigned const val =
m /(m%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30
+ m%0x3fffffffL /(m%31+1)/31%31*5 + 4-12/(m%31+3);
};
};
template<class T>
struct AmountValueBits {
static unsigned const val = IMaxBits<T>::template AllOnes<-1>::val;
};
#include <cstdlib>
#include <cstring>
#include <cstddef>
#include <cassert>
template<std::size_t width>
inline const char* CenterHoriz( const char * const p )
{
using std::memset;
using std::strlen;
using std::size_t;
static char spaces[width + 1];
memset( spaces, ' ', width );
size_t const len = strlen( p );
assert( width >= len );
char * const pos = spaces + ( width / 2 - len / 2 );
memcpy( pos, p, len );
return spaces;
}
#include <iostream>
extern char const str_uchar[] = "unsigned char";
extern char const str_ushort[] = "unsigned short";
extern char const str_uint[] = "unsigned int";
extern char const str_ulong[] = "unsigned long";
template<class T, const char* str>
void PrintRow()
{
using std::cout;
unsigned const total_bits = sizeof(T) * AmountValueBits<unsigned
char>::val;
unsigned const val_bits = AmountValueBits<T>::val;
unsigned const pad_bits = total_bits - val_bits;
const char * const spaces_val =
val_bits > 99 ? "" : ( val_bits > 9 ? " " : " " );
const char * const spaces_pad =
pad_bits > 99 ? "" : ( pad_bits > 9 ? " " : " " );
const char * const spaces_total =
total_bits > 99 ? "" : ( total_bits > 9 ? " " : " " );
cout << "||" << CenterHoriz<21>(str) << "|| "
<< spaces_val << val_bits << " || " << spaces_pad <<
pad_bits
<< " || " << spaces_total << total_bits << " ||\n"
"---------------------------------------------------------------------
\n";
}
int main()
{
using std::cout;
cout <<
"
==============================================\n"
" || Value bits || Padding Bits || Total Bits
||\n"
"=====================================================================
\n";
PrintRow<unsigned char, str_uchar>();
PrintRow<unsigned short, str_ushort>();
PrintRow<unsigned, str_uint>();
PrintRow<unsigned long, str_ulong>();
cout << "\n\n\n";
std::system( "PAUSE" );
}
I'd be interested to hear if anyone gets some "interesting" values.