我试图在32位Linux平台上运行以下程序。
int main()
{
unsigned long long val = 0;
val = 140417 * 100000 + 92 + 1;
}
输出是一些垃圾值(1156798205)。
经过一番研究,我发现:here
long long size: 64 bits (MAX VALUE: signed long long = 144115188075855871, unsigned long long = 1073741823)
对于数据类型unsigned long long和signed long long,上面的代码给Visual Studio 2005带来了同样的问题。
但是根据MSDN文档: here
unsigned long long 8 byte range of values 0 to 18,446,744,073,709,551,615
我想知道如何使用C ++程序在32位Linux平台上处理大范围的值。
谢谢你的帮助。
答案 0 :(得分:1)
问题是非整数常量的类型(如42
)是int
,long int
,long long int
中可以保存其值的最小值,以及表达式的类型由表达式本身决定,而不是由它出现的上下文决定。
因此,如果int
恰好是您系统上的32位,那么请执行以下操作:
unsigned long long val = 140417 * 100000 + 92 + 1;
常量140417
和100000
(两者都适合32位)的类型为int
,乘法是32位乘法 - 由于乘积而溢出这两个数字不适合32位。 (独立文字的类型根据其值进行调整;较大表达式的类型不是。)
避免这种情况最直接的方法是使用unsigned long long
类型的常量:
unsigned long long val = 140417ULL * 100000ULL + 92ULL + 1ULL;
(碰巧并非所有ULL
后缀都是必需的,但将它们应用于表达式中的所有常量并没有什么坏处。)
答案 1 :(得分:0)
如果您打印出:sizeof(unsigned long long)
,则最大值为2 ^(该值)-1。
答案 2 :(得分:0)
问题是虽然您使用的是64位数据类型,但您的计算使用32位值,因此您遇到整数溢出。 140417 * 100000
在64位是14041700000(0x344F356A0),但在32位是1156798112(0x44F356A0)。如您所见,0x300000000被截断结果,因为它不适合32位值。
您需要确保使用64位计算,例如:
typedef unsigned long long ulong64_t;
int main()
{
ulong64_t val = 0;
val = ulong64_t(140417) * ulong64_t(100000) + 92 + 1;
}
或者,使用整数常量后缀:
int main()
{
unsigned long long val = 0;
val = 140417i64 * 100000i64 + 92 + 1;
}
或者:
int main()
{
unsigned long long val = 0;
val = 140417ull * 100000ull + 92 + 1;
}
答案 3 :(得分:0)
我想知道如何使用C ++程序在32位Linux平台上处理大范围的值。
添加#include <stdint.h>
并使用明确long long
或最好int64_t
或uint64_t
类型。
最近的海湾合作委员会(例如,现已于2014年4月中旬发布的GCC 4.9)可能有__int128
。
如果你想处理非常大的数字(绝对值大于2 63 ),所谓的bignums你需要一个bignum库(比如GMPlib) ,或者是一种支持它们的语言(例如Common Lisp,使用SBCL ....)
BTW,以下计划
#include <stdio.h>
int main () {
unsigned long long val = 0;
val = 140417 * 100000LL + 92 + 1;
printf ("val=%lld\n", val);
return 0;
}
在Linux x86 32位上运行正常。如果省略LL
100000
后缀{后缀为LL
以获得long long
字面值100000常量),则会在integer overflow in expression >使用gcc -Wall hpfe.c -o hpfe
....编译时间。