C 如何获得用宏存储整数值所需的最少字节数?
例如,如果整数小于255,则可以在1字节中恢复该整数 如果大于255,则至少需要2字节C 如何获得用宏存储整数值所需的最少字节数?,c,macros,C,Macros,例如,如果整数小于255,则可以在1字节中恢复该整数 如果大于255,则至少需要2字节 如何编写这样一个字节\u所需(i)宏?如果您使用的是C99编译器,请将下面的转换转换为(unsigned long)。 此外,您还可以(并且应该)将构造扩展到8或16字节(这只是一个练习) #包括 #定义所需字节(i)\ !((无符号长)(i)>>字符位)?1 \ : !((无符号长)(i)>>2*字符位)?2 \ : !((无符号长)(i)>>3*字符位)?3 \ :
如何编写这样一个
字节\u所需(i)
宏?如果您使用的是C99编译器,请将下面的转换转换为(unsigned long)
。
此外,您还可以(并且应该)将构造扩展到8或16字节(这只是一个练习)
#包括
#定义所需字节(i)\
!((无符号长)(i)>>字符位)?1 \
: !((无符号长)(i)>>2*字符位)?2 \
: !((无符号长)(i)>>3*字符位)?3 \
: 4
这使用了一种有效的分而治之的方法:
#define BYTES_REQUIRED(i) (((i) & 0xFFFF0000) ? (((i) & 0xFF000000) ? 4 : 3) : (((i) & 0xFF00) ? 2 : 1))
如果您不介意消除3字节的奇数大小写,它没有与之匹配的基元类型,请执行以下操作:
#define BYTES_REQUIRED(i) (((i) & 0xFFFF0000) ? 4 : (((i) & 0xFF00) ? 2 : 1))
请注意,这两种方法都不能处理负数,因为它将符号扩展1位视为已用空间。这需要考虑另一个条件(例如,如果为负,则为否定)。您实际上需要计算log2(i)。对于编译器和宏所支持的最大整数值,没有一种简单的方法可以方便、快速地实现这一点 选项: 1.计算循环中的对数:
// 64+-bit version:
unsigned long BYTES_REQUIRED(unsigned long long i)
{
unsigned long bits = 0;
while (i)
{
i >>= 1;
bits++;
}
if (bits == 0) bits = 1;
return (bits + 7) / 8; // we're assuming that byte=8 bits, but CHAR_BIT may be > 8
}
2.使用编译器的内部函数(有效地,专用CPU指令),如果可用。对于MSVC++:
// 64-bit version, not available for 32-bit code:
unsigned long BYTES_REQUIRED(unsigned long long i)
{
unsigned long index;
if (_BitScanReverse64(&index, i) == 0)
{
index = 1;
}
return (index + 8) / 8;
}
// 32-bit version, available for 32 and 64-bit code:
unsigned long BYTES_REQUIRED(unsigned long i)
{
unsigned long index;
if (_BitScanReverse(&index, i) == 0)
{
index = 1;
}
return (index + 8) / 8;
}
// 64-bit version available for 32 and 64-bit code:
unsigned long BYTES_REQUIRED(unsigned long long i)
{
unsigned long index;
if (_BitScanReverse(&index, (unsigned long)(i >> 32)))
{
index += 32;
}
else if (_BitScanReverse(&index, (unsigned long)i) == 0)
{
index = 1;
}
return (index + 8) / 8;
}
3.如果
或?:
知道支持的最大整数类型的大小,请使用。。。其他人已经描述了这个方法。< P>不幸的是,你要求一个C宏,因为这个C++模板函数可能是有用的(它应该适用于编译器支持的任何整数类型)。
需要模板int字节(T值){
boost::function_需要();
对于(int i=0;iWhy a macro?你知道如何使用普通函数吗?@Mat,事实上我只能想到这个:if(i255&&i<2^16)return 2;…
,太长了,不能作为宏。为什么需要宏?@Mat,在我的例子中,i
都是常量,我需要一个宏,这样可以在编译时计算结果,没有运行时开销。那么i
s的范围是多少?32位?64位?更多?如果是c99 com,为什么我需要将其转换为无符号的long-long-longpiler?因为C89无法识别unsigned long
,它至少与unsigned long
一样大。使用unsigned long
不会丢失任何东西(C89兼容性除外)并且可能获得更大范围的工作值。解决log-base-2可以提高位的精度,这是不需要的。你正在解决一个更难的问题,然后他问,然后将额外的精度分开。BitScanReverse可能有点道理,因为它在某些处理器上速度很快,但他要求在编译时解决,因此性能rmance无论如何都是无关紧要的。instrinsic降低了代码的可移植性,并且不做任何交换。
// 64-bit version, not available for 32-bit code:
unsigned long BYTES_REQUIRED(unsigned long long i)
{
unsigned long index;
if (_BitScanReverse64(&index, i) == 0)
{
index = 1;
}
return (index + 8) / 8;
}
// 32-bit version, available for 32 and 64-bit code:
unsigned long BYTES_REQUIRED(unsigned long i)
{
unsigned long index;
if (_BitScanReverse(&index, i) == 0)
{
index = 1;
}
return (index + 8) / 8;
}
// 64-bit version available for 32 and 64-bit code:
unsigned long BYTES_REQUIRED(unsigned long long i)
{
unsigned long index;
if (_BitScanReverse(&index, (unsigned long)(i >> 32)))
{
index += 32;
}
else if (_BitScanReverse(&index, (unsigned long)i) == 0)
{
index = 1;
}
return (index + 8) / 8;
}
template <typename T> int bytesRequired(T value) {
boost::function_requires< boost::IntegerConcept<T> >();
for (int i=0; i<=sizeof(T); i++, value/=256)
if (value == 0) return i;
}