C++ - 获取整数的位数

13
我需要知道一个整数是否有32位长(我想知道它是否恰好有32位长(8个十六进制字符)。我该如何在C++中实现这一点?我应该使用十六进制表示还是unsigned int表示?

我的代码如下:

mistream.open("myfile.txt");

if(mistream)
{
    for(int i=0; i<longArray; i++)
    {
        mistream >> hex >> datos[i];        
    }
}

mistream.close();

其中,mistream是ifstream类型,datos是无符号整型数组

谢谢


6
使用 <limits.h> 并计算 sizeof(int)*CHAR_BIT 或测试 INT_MAX/INT_MIN - chux - Reinstate Monica
我不确定您想知道在您的平台上,类型为“int”的变量使用了多少位,还是表示特定整数值需要多少位。一个整数可能需要32位,但仅需要1位来表示值0。 - R Sahu
1
一种非可移植的方法是使用非标准内置函数。大多数计算机都有指令来计算前导零或前导冗余符号位。 - user3528438
请明确一下:您是想知道_type_是否为32位,还是_value_是否在power(2,31)power(2,32)-1之间,或者其他什么? - chux - Reinstate Monica
是的@chux,我想知道这个值是否在2的31次方和2的32次方减1之间。你能帮我吗?谢谢。 - fergaral
只是一个吹毛求疵的提醒,一个数字可以用少于32位来表示,但仍然需要"8个十六进制字符",例如0x1000'0000只使用了29位。考虑从你的问题中删除关于8个十六进制字符的备注。 - undefined
6个回答

23
std::numeric_limits<unsigned>::digits

这是一个静态的整数常量(在C++11中为constexpr),它给出了位数的数量(因为unsigned是以二进制存储的,所以它给出了二进制数字)。

您需要#include <limits>来获取此信息,并且您会注意到此处提供了与Thomas答案相同的值(同时也适用于其他基本类型)


作为参考(您在我回答后更改了问题),给定程序中给定类型(例如,unsigned)的每个整数大小完全相同

您现在要问的不是整数的位数,因为它从未变化过,而是顶部位是否设置。 您可以使用以下简单的测试进行测试:

bool isTopBitSet(uint32_t v) {
  return v & 0x80000000u;
}

(如果您想扩展到除uint32_t以外的无符号T,请用类似于T{1} << (std::numeric_limits<T>::digits-1)的内容替换无符号十六进制文本。)


我该怎么使用呢?我的意思是,我有一个无符号整数数字,我如何使用你的方法呢? - fergaral
@fergaral 你的意思是什么?你只需要类型,而不是值本身。 - Neil Kirk

7

正如@chux的评论中已经暗示的那样,您可以使用sizeof运算符和CHAR_BIT宏常量的组合。前者告诉您(在编译时)其参数类型的大小(以sizeof(char)即字节为单位)。后者是每个字节的位数(通常为8)。

您可以将此封装成一个很好的函数模板。

#include <climits>   // CHAR_BIT
#include <cstddef>   // std::size_t
#include <iostream>  // std::cout, std::endl

template <typename T>
constexpr std::size_t
bit_size() noexcept
{
  return sizeof(T) * CHAR_BIT;
}

int
main()
{
  std::cout << bit_size<int>() << std::endl;
  std::cout << bit_size<long>() << std::endl;
}

在我的实现中,它输出32和64。
由于该函数是一个constexpr,你可以在静态上下文中使用它,例如在static_assert<bit_size<int>() >= 32, "too small");中。

1
struct Foo { int a : 5; int b : 13; }; 有没有办法使用 bit_size<Foo::a> 返回 5? - Eljay

5
试试这个:
#include <climits>

unsigned int bits_per_byte = CHAR_BIT;
unsigned int bits_per_integer = CHAR_BIT * sizeof(int);

标识符CHAR_BIT表示一个char中的位数。

sizeof返回整数占用的char位置数。

将它们相乘可以得到整数的位数。


CHAR_BITS的值是多少?我的意思是确切的值,如果不知道,我该如何获取它?谢谢。 - fergaral
1
宏被命名为CHAR_BIT(单数),并且它是在climits中定义的,而不是在cstdint中:http://en.cppreference.com/w/cpp/types/climits - 5gon12eder
我是这样做的:unsigned int bits_per_integer = CHAR_BITS * sizeof(myarray[i]),但它总是返回32。我做错了什么? - fergaral
32是32位架构机器上int类型的正确位数。@ChristopherCreutzig,你从哪里得到了29位? - user3629249
如果myarray是一个int数组,并且在您的系统上int是32位(在现代系统上几乎是这种情况),那么显然CHAR_BIT*sizeof(myarray[i])将始终返回32,即int或myarray[i]中的位数。你还期望什么? - phuclv
显示剩余6条评论

0
我想知道它是否确切地是32位长(8个十六进制字符)。
我想知道这个值是否介于2的31次方和2的32次方-1之间。
所以你想知道上限位是否设置?那么你可以简单地测试这个数字是否为负数:
bool upperBitSet(int x)
{
    return x < 0;
}

对于无符号数,您可以简单地左移和右移,然后检查是否丢失数据:

bool upperBitSet(unsigned x)
{
    return (x << 1 >> 1) != x;
}

0
OP说:“如果它的长度正好是32位(8个十六进制字符)”,并进一步表示“我想知道该值是否介于2的31次方和2的32次方减1之间”。所以对于负的32位数字有点模糊。
当然,OP希望根据值而不是类型来得到结果。
bool integer_is_32_bits_long(int x) = 
    // cope with 32-bit int
    ((INT_MAX == 0x7FFFFFFF) && (x < 0)) ||
    // larger 32-bit int
    ((INT_MAX >  0x7FFFFFFF) && (x >= 0x80000000) && (x <= 0xFFFFFFFF));

当然,如果int是16位,则结果始终为false


-2

最简单的方法可能是检查第32位是否被设置:

bool isReally32bitsLong(uint32_t in) {
  return (in >> 31)!=0;
}

bool isExactly32BitsLong(uint64_t in) {
  return ((in >> 31)!=0) && ((in >> 32) == 0);
}

2
1UL << 32 可能存在问题。 - chux - Reinstate Monica
2
不,这显然是一个问题。 - user3528438
@MooingDuck 为什么要用Windows?几乎所有32位机器上的实现都使用32位的“long”。 - user3528438
1
@user3528438:具体来说,_Visual Studio_(编译几乎所有 Windows 程序所使用的编译器)在为 64 位机器编译时使用 32 位长整型。而 Clang 和 G++ 在为 64 位机器编译时使用 64 位长整型。long 是一种语言特性,因此重要的是编译器而不是硬件。 - Mooing Duck
@ThomasMatthews 这是什么意思?我回答中的代码现在只使用指定宽度的整数,没有16位整数。 - Christopher Creutzig
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接