1

C/C++ 中有没有一种方法可以使用 sizeof 运算符计算某种数据类型可表示的 2 的最大幂?

例如,假设我有一个unsigned short int. 它的值可以在0和之间65535。因此 anunsigned short int可以包含的最大二的幂是32768

我将它传递unsigned short int给一个函数,我(目前)和算法看起来像这样:

if (ushortParam > 32768) {
    ushortParam = 32768; // Bad hardcoded literals
}

但是,将来,我可能想更改变量类型以合并更大的 2 次方。是否有使用 sizeof() 的与类型无关的公式可以实现以下目标:

if (param > /*Some function...*/sizeof(param) )
{
    param = /*Some function...*/sizeof(param);
}

请注意,该参数永远不需要浮点精度 - 仅整数。

4

4 回答 4

4

设置该参数大小的变量的最高有效位将为您提供 2 的最高幂。

1 << (8*sizeof(param)-1)
于 2012-10-20T11:17:06.757 回答
3

关于什么:

const T max_power_of_two = (std::numeric_limits<T>::max() >> 1) + 1;
于 2012-10-20T11:17:51.517 回答
2

要获得某个整数类型可表示的 2 的最高幂,您可以使用它limits.h来代替sizeof运算符。例如:

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

int main() {

  int max   = INT_MAX;
  int hmax  = max>>1;
  int mpow2 = max ^ hmax;

  printf("The maximum representable integer is %d\n",max);
  printf("The maximum representable power of 2 is %d\n",mpow2);
  return 0;
}

这应该始终有效,因为始终定义正整数的右移。引用标准 C 第 6.5.7.5 节(按位移位运算符):

E1 >> E2的结果是E1右移E2位位置。如果E1 具有无符号类型或E1具有有符号类型和非负值,则结果的值是 E1的商除以数量的整数部分,2 的幂E2

如果使用sizeof是强制性的,您可以使用:

1 << (CHAR_BIT*sizeof(param)-1)

对于无符号整数类型和:

1 << (CHAR_BIT*sizeof(param)-2)

对于有符号整数类型。上面的行仅适用于没有填充位的整数类型。确保这些线路正常工作的标准 C 部分在第 6.2.6.2 节中。尤其是:

对于 unsigned char以外的无符号整数类型,对象表示的位应分为两组:值位和填充位(后者不需要任何一个)。如果有 N 个值位,每个位应表示 1 和 2N-1 之间的 2 的不同幂,以便该类型的对象应能够使用纯二进制表示表示从 0 到 2N-1 的值;这应称为值表示。

保证第一种方法在以下情况下起作用:

对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位;应该只有一个符号位。

...

符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并且应表示相同的值。

解释了为什么第二行给出了正确的答案。

于 2012-10-20T13:01:21.970 回答
0

接受的答案可能适用于 Posix 平台,但不是通用的 C/C++。它假定 CHAR_BIT 为 8,不指定类型,并假定该类型没有填充位。

以下是任何/所有无符号整数类型的更通用版本,不需要包含任何标题、依赖项等:

#define MAX_VAL(UNSIGNED_TYPE) ((UNSIGNED_TYPE) -1)

#define MAX_POW2(UNSIGNED_TYPE) (~(MAX_VAL(UNSIGNED_TYPE) >> 1))

#define MAX_POW2_VER2(UNSIGNED_TYPE) (MAX_VAL(UNSIGNED_TYPE) ^ (MAX_VAL(UNSIGNED_TYPE) >> 1))

#define MAX_POW2_VER3(UNSIGNED_TYPE) ((MAX_VAL(UNSIGNED_TYPE) >> 1) + 1)

标准,甚至 C90,保证将 -1 强制转换为无符号类型总是产生该类型可以表示的最大值。从那里开始,上面的所有按位运算符都得到了很好的定义。

http://c0x.coding-guidelines.com/6.3.1.3.html

6.3.1.3 有符号和无符号整数

682 当整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新的类型表示,则保持不变。

683否则,如果新类型是无符号的,则在新类型所能表示的最大值的基础上反复加减1,直到该值在新类型的范围内。

684 否则,新类型有符号,值不能在其中表示;

685 结果是实现定义的,或者产生了实现定义的信号。

无符号类型的最大值是 2 的幂次方小 1,并且设置了所有值位。上述表达式导致仅设置最高位,这是该类型可以表示的 2 的最大幂。

http://c0x.coding-guidelines.com/6.2.6.2.html

6.2.6.2 整数类型

593 对于 unsigned char 以外的无符号整数类型,对象表示的位应分为两组:值位和填充位(后者不需要任何一个)。

594 如果有 N 个值位,每个位应表示 1 和 2^(N - 1) 之间的 2 的不同幂,因此该类型的对象应能够使用 a 表示从 0 到 2^N - 1 的值纯二进制表示;

595 这应称为值表示。

596 未指定任何填充位的值。

于 2017-09-26T15:37:38.633 回答