Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何获得用宏存储整数值所需的最少字节数?_C_Macros - Fatal编程技术网

C 如何获得用宏存储整数值所需的最少字节数?

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 \ :

例如,如果整数小于255,则可以在1字节中恢复该整数

如果大于255,则至少需要2字节


如何编写这样一个
字节\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;
}