探讨int和unsigned能表示的最大的数和最小的数

 

一个 int 占4个字节,就是32个比特位,所以能表示的范围为-2^31~+2^31-1 2,147,483,647。

若是unsigned int,能表示的范围是0 ~ +2^32-1 4,294,967,295 约43亿,与地球人口还差那么一大段距离(约78亿)

看一段源码:

#include <iostream>
#include <math.h>
using namespace std;
int main(){

 //4个字节的unsigned int能表示的最大数为2的32次方减1; 
 //pow的返回类型是double,需要强制转换成unsigned int
  unsigned  int max = static_cast<unsigned int>(pow(2.0,32) - 1);
  //test值为0,验证此方法行不通,原因见附录
  unsigned int test = 1 << 32;  
  //max+1就超出了unsigned int的表示范围 
   cout << "unsigned int max value:" << max << endl 
        << "then max+1:" << max+1 << endl; 
    //int能表示的最小负数-2^31
  cout << "int min value:-" << static_cast<int>(pow(2.0,31)) << endl;
  //4个字节的int能表示的最大正数,不过有警告left shift count >= width of type 
   cout << "int max value:" << (1 << 31) - 1 << endl; 
   //1默认是int型,要把它指定成unsigned int后正确
 cout << "unsigned int max value:" << (1U << 32) - 1 << endl; 
}

运行结果:

unsigned int max value:4294967295
then max+1:0
int min value:-2147483648
int max value:2147483647
unsigned int max value:4294967295
pow(2.0,1000):1.07151e+301

 

 

附录:

1:使用pow(2.0,n);返回的值是double型,可表达的最大值我不知道,不过n的值在1000之内都是可以的

pow(2.0,1000) = 1.07151e+301;

pow(2.0,2000) = Infinity

2:int占两个字节的时代已经过去,目前几乎所有编译器都给int分配4个字节

3:关于warning:left shift count >= width of type

I'm very new to dealing with bits and have got stuck on the following warning when compiling:

7: warning: left shift count >= width of type 

My line 7 looks like this

unsigned long int x = 1 << 32; 

This would make sense if the size of long on my system was 32 bits. However, sizeof(long) returns 8 and CHAR_BIT is defined as 8 suggesting that long should be 8x8 = 64 bits long.

What am I missing here? Are sizeof and CHAR_BIT inaccurate or have I misunderstood something fundamental?

link | improve this question

 
 
feedback

2 Answers

up vote 11 down vote accepted

long may be a 64-bit type, but 1 is still an int. You need to make1 a long int using the L suffix:

unsigned long x = 1UL << 32; 

(You should also make it unsigned using the U suffix as I've shown, to avoid the issues of left shifting a signed integer. There's no problem when along is 64 bits wide and you shift by 32 bits, but it would be a problem if you shifted 63 bits)

link | improve this answer
 
Would unsigned long x = 1; x <<= 32; work, out of interest? –  Kolink Nov 17 '10 at 3:53
 
@Kolink: Yes, that would have the same effect, as would(unsigned long)1 << 32 The left operand just has to be an unsigned long. TheUL suffix is just the most straightforward way to accomplish that. –  James McNellis Nov 17 '10 at 4:03
> Hi,
> here's a simple program snippet that I'm dealing with and worried about
> potential pitfalls:

> #define BITS_PER_UNIT 32
> [...]
> int foo, bar;

> bar = 0xAAAA5555;
> foo = bar & ~ ((int) 1 << BITS_PER_UNIT);
> [...]

> Strictly speaking the shift operations should report a warning (left
> shift count >= width of type), since 1 is of type int (correct me if I'm
> wrong).

There's no guarantee that the shift count >= the width of the type,
since 'int' could be, for instance, a 64-bit type.

The relevant clause is phrased in terms of whether not the the result
can be represented in the type, not the width of the type, For the
expression E1 << E2, "If E1 has a signed type and nonnegative value, and
E1 x 2^E2 is representable in the result type, then that is the
resulting value; otherwise, the behavior is undefined" (6.5.7p5)

Therefore, for a 32-bit int, even 1 << 31 is problematic. That's an
example of why it's better to use unsigned types for most bit-masking
purposes.

However - and this is the key point - this is not a constraint, it's
undefined behavior. Conforming implementations are NOT required to issue
a diagnostic.

> Since this snippet is part of a very old implementation of g21k compiler
> for ADSP21xxx, I'm wondering why do we need to shift at all, isn't the
> above foo assignment equal to the following:
 
In addition (C99 6.5.7):

    If the value of the right operand is negative or is greater than or
    equal to the width of the promoted left operand, the behavior is
    undefined.

So for a 32-bit type, even 0<<32 or 0>>32 has undefined behavior, even
though the mathematical result is representable.

[...]

--
Keith Thompson (The_Other_Keith) ks...@mib.org  <http://www.ghoti.net/~kst>
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"


Others have mentioned the undefined behavior if int is 32 bits.

Let's assume that ints contain more than 33 bits to eliminate the undefined
behavior.  I'll assume that ints are 40 bits.

The assignment to foo is equivalent to
  foo = bar & (int)0xfeffffffff;

when the programmer probably intended

  foo = bar & 0x00ffffffff;

To keep the lower BITS_PER_UNIT bits (at least one) I would have written

  foo = bar & (((1u << (BITS_PER_UNIT-1))-1)*2 +1);

That should work, assuming the implementation has at least BITS_PER_UNIT bits in
an unsigned int.  If bar is an unsigned int, then replace 1u with 1ul.

The embedded compiler I work with optimizes out anding with all one bits, so it
would have no run-time penalty.

Thad



> foo = bar;

Since this code has undefined behavior if INT_MAX < pow(2,32), I would
hope that it was intended for an implementation where INT_MAX >
pow(2,32). I  have no idea whether the "g2lk compiler for ADSP21xxx" is
such an implementation. If it were, then the foo assignment statement
would not be equivalent to "foo = bar".

However, it seem more plausible that the author of this code didn't know
or care about the fact that it had undefined behavior; it did what he
wanted it to do on the particular implementation where it needed to
work, and no attention was paid to whether or not it would do so
anywhere else.
--
James Kuyper


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值