首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

64位系统上,整数溢出的有关问题

2013-02-15 
64位系统下,整数溢出的问题1929double aa MSGBUFSIZE*100000(gdb) 1930int bb MSGBUFSIZE*100000(gd

64位系统下,整数溢出的问题

1929            double aa = MSGBUFSIZE*100000;
(gdb) 
1930            int bb = MSGBUFSIZE*100000;
(gdb) 
1931            unsigned int cc = MSGBUFSIZE*100000;
(gdb) 
1932            unsigned long long dd = MSGBUFSIZE*100000;
(gdb) 
1933            int64_t ee = MSGBUFSIZE*100000;
(gdb) 
1934            uint64_t ff = MSGBUFSIZE*100000;
(gdb) 
1937            while ((i = getopt (argc, argv, "b")) != -1)
(gdb) p aa
$1 = -1004967296
(gdb) p bb
$2 = -1004967296
(gdb) p cc
$3 = 3290000000
(gdb) p dd
$4 = 18446744072704584320
(gdb) p ee
$5 = -1004967296
(gdb) p ff
$6 = 18446744072704584320
(gdb) p sizeof(aa)
$7 = 8
(gdb) p sizeof(bb)
$8 = 4
(gdb) p sizeof(cc)
$9 = 4
(gdb) p sizeof(dd)
$10 = 8
(gdb) p sizeof(ee)
$11 = 8
(gdb) p sizeof(ff)
$12 = 8
(gdb) 

其中只有cc 的值 3290000000 是正确的, 其他的值都是错误的。
为何unsigned long long 也是错误的 ? 为何 int64_t  和 uint64_t也是错误的。
我已经包含了头文件   
#include <stdint.h>
#include <unistd.h>

也定义了  #define _FILE_OFFSET_BITS 64 这个测试过,结果都一样。

我编译出来的可执行文件  用 file查看也是64为的PE文件。  
[解决办法]
试试

MSGBUFSIZE*100000U

[解决办法]
MSGBUFSIZE具体数值多少?

[解决办法]
32900*100000  是以int来计算的,它已经溢出

把溢出的值再赋给其它类型,并做相应的转换结果当然不对啊
[解决办法]
引用:
32900*100000  是以int来计算的,它已经溢出

把溢出的值再赋给其它类型,并做相应的转换结果当然不对啊

+1
unsigned int cc = MSGBUFSIZE*100000;其实也是溢出了的,只是把int隐式转换成unsigned int 刚好把最高的符号位当成有效位了,所以就是正确的。为什么会刚好对呢?假设MSGBUFSIZE*100000计算得到的结果是:-1004967296,用16进制表示是:0xc4196a80(这个是补码,计算机保存数据都是补码形式)。从这个16进制的表示结果就可以看书已经产生溢出了,因为两个正数相乘的最高位有进位了,本来最高位是0,现在是1了,所以出现了两个大正数计算的结果是一个负数。当将int隐式转换成unsigned int时,最高位(刚才的进位)不在被看成符号位了,所以就刚好是就算的结果。



[解决办法]

unsigned int v = 32900*100000;//warning: overflow in implicit constant conversion



unsigned int v = 32900*100000U;//type promotion, it's fine here

[解决办法]
只需要这个值的话u就可以了,再大就要上ll了
------解决方案--------------------


常量也有类型!
以下内容摘自MSDN2008:

Visual C++ Language Reference
C++ Integer Constants

Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.

Grammar
integer-constant: 
decimal-constant integer-suffixopt

octal-constant integer-suffixopt

hexadecimal-constant integer-suffixopt

'c-char-sequence'

decimal-constant: 
nonzero-digit 

decimal-constant digit

octal-constant: 
0

octal-constant octal-digit

hexadecimal-constant: 
0xhexadecimal-digit

0Xhexadecimal-digit 

hexadecimal-constant hexadecimal-digit

nonzero-digit: one of 
1 2 3 4 5 6 7 8 9

octal-digit: one of 
0 1 2 3 4 5 6 7

hexadecimal-digit: one of 
0 1 2 3 4 5 6 7 8 9 

a b c d e f 

A B C D E F

integer-suffix: 
unsigned-suffix long-suffixopt

long-suffix unsigned-suffixopt

unsigned-suffix: one of 
u U

long-suffix: one of 
l L

64-bit integer-suffix: 
i64 LL ll

To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.

To specify a decimal constant, begin the specification with a nonzero digit. For example:

  Copy Code 
int i = 157;   // Decimal constant
int j = 0198;  // Not a decimal number; erroneous octal constant
int k = 0365;  // Leading zero specifies octal constant, not decimal
 

To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:

  Copy Code 
int i = 0377;   // Octal constant
int j = 0397;   // Error: 9 is not an octal digit
 

To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the "x" does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:



  Copy Code 
int i = 0x3fff;   // Hexadecimal constant
int j = 0X3FFF;   // Equal to i
 

To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:

  Copy Code 
unsigned uVal = 328u;             // Unsigned value
long lVal = 0x7FFFFFL;            // Long value specified 
                                  //  as hex constant
unsigned long ulVal = 0776745ul;  // Unsigned long value
 

To specify a 64-bit integral type, use the LL, ll or i64 suffix. For example,

  Copy Code 
// 64bitsuffix.cpp
#include <stdio.h>
enum MyEnum {
   IntType,
   Int64Type
};

MyEnum f1(int) {
   printf("in f1(int)\n");
   return IntType;
}

MyEnum f1(__int64) {
   printf_s("in f1(__int64)\n");
   return Int64Type;
}

int main() {
   MyEnum t1 = f1(0x1234), t2 = f1(0x1234i64);
}
 

Output
  
in f1(int)
in f1(__int64)
 

See Also
Concepts
Literals (C++)
Send feedback on this topic to Microsoft.

热点排行