一个 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?
|
|
feedback
|
|
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)
|
|
answered
Nov 17 '10 at 3:49
| |
|
|
> 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