例如,如果整数小于255,则可以在 1 字节中恢复,
如果大于255,则需要至少 2 字节。
如何编写这样的BYTES_REQUIRED(i)
宏?
答案 0 :(得分:0)
如果您使用的是C99编译器,请将下面的强制转换为(unsigned long long)
。
您也可以(并且应该)将构造扩展为8或16个字节(作为练习留下)
#include <limits.h>
#define BYTES_REQUIRED(i) \
!((unsigned long)(i) >> CHAR_BIT) ? 1 \
: !((unsigned long)(i) >> 2 * CHAR_BIT) ? 2 \
: !((unsigned long)(i) >> 3 * CHAR_BIT) ? 3 \
: 4
答案 1 :(得分:0)
这采用了一种有效的分而治之的方法:
#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位作为已用空间。这需要另一个条件来解释(例如,如果否定,否定)。
答案 2 :(得分:0)
您实际上需要计算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.使用if
或?:
知道支持的最大整数类型的大小......其他人已经描述了这种方法。
答案 3 :(得分:0)
不幸的是你要求一个C宏,因为这个C ++模板化的函数可能有用(它适用于你的编译器支持的任何整数类型)。
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;
}
另一种应该更快的方法(因为它是无分支的),如果你不需要编译时评估,那就是Alex提到的位扫描。