在64位可执行文件中执行64位计算
Perform 64 bit calculations in 64 bit executable
我正在使用MinGW64(带有-m64
标志)与Code::Blocks,我希望知道如何执行64位计算,而无需在乘以它之前将一个非常大的数字转换为int64_t
。例如,这不会导致溢出:
int64_t test = int64_t(2123123123) * 17; //Returns 36093093091
如果没有强制转换,计算就会像这样溢出:
int64_t test = 2123123123 * 17; //Returns 1733354723
VirusTotal扫描确认我的可执行文件是x64。
附加信息:操作系统为Windows 7 x64。
出于兼容性考虑,即使在64位编译中,默认的int类型仍然是32位。
我想"最短"的版本是在数字
后面加上ll
后缀。int64_t test = 2123123123ll * 17;
另一种方法是将数字存储在它们自己的int64_t
(或long long
)类型的变量中,并将变量相乘。通常情况下,在程序中将许多"神奇数字"硬编码到代码库中是很少见的。
一些背景:
从前,大多数计算机都有8位算术逻辑单元和16位地址总线。我们称它们为8位计算机。
我们学到的第一件事是,现实世界中的算术问题不能用8位表示。这就像试图用黑猩猩的算术能力来推理太空飞行一样。所以我们学会了写多字的加、乘、减、除数列。因为在大多数现实问题中,问题的数值定义域大于255。
我们短暂地拥有16位计算机(同样的问题也适用,65535不足以建模),然后很快,32位算术逻辑内置到芯片中。渐渐地,地址总线赶上了(20位,24位,32位,如果设计者觉得奢侈的话)。
然后一件有趣的事情发生了。我们大多数人不再需要编写多字等差数列了。事实证明,大多数(tm)现实世界中的整数问题都可以用32位(最多40亿)来表示。然后我们开始以比以往更快的速度产生更多的数据,我们意识到需要处理更多的内存。64位计算机最终成为标准。
但是,大多数现实世界的整数算术问题都可以用32位来表示。对于大多数事情来说,40亿是一个足够大的数字。
所以,大概是通过统计分析,你的编译器编写者决定在你的平台上,int类型最有用的大小是32位。任何更小的值对于32位算术运算来说都是低效的(这是我们从第一天开始就需要的),任何更大的值都会浪费空间/寄存器/内存/cpu周期。
在c++(和c)中表示整数字面值会产生int——环境的自然算术大小。现在,它几乎总是一个32位的值。
c++规范规定两个int型相乘得到一个int型。如果没有,那么两个int相乘就会得到一个long。那么两个长期债券相乘的收益是多少呢?一个长长的长?好吧,这是可能的。如果把它们相乘呢?一个长长的长长的长长的?
就是这样。
int64_t x = 1 * 2;
将执行以下操作:
- 取值1的整数(32位)
- 取值2的整数(32位)
- 将它们相乘,将结果存储为整数。如果算术溢出,那就这样吧。那是你的事。
- 将结果整数(无论现在可能是什么)强制转换为int64(可能在您的系统上是
long int
)。
所以简单地说,没有。在问题的代码片段中,没有捷径可以拼写出至少一个操作数的类型。当然,您可以指定一个文字。但是不能保证系统上的long long
(LL字面值后缀)与int64_t
相同。如果你想要一个int64_t
,并且你希望代码是可移植的,你必须把它拼出来。
无论如何:
在c++11之后的世界里,所有关于额外击键和非干燥的担忧都将消失:
绝对是int64:
auto test = int64_t(2123123123) * 17;
a long long:
auto test = 2'123'123'123LL * 17;
肯定是int64,肯定是用long(可能是窄化的,但没关系)long:
初始化的。auto test = int64_t(36'093'093'091LL);
由于您很可能处于LP64环境中,其中int
只有32位,因此您必须小心表达式中的文字常量。要做到这一点,最简单的方法是养成在文字常量上使用适当后缀的习惯,因此您可以将上面的代码写成:
int64_t test = 2123123123LL * 17LL;
2123123123
是int
(通常为32位)。
添加L
使其成为long
: 2123123123L
(通常为32位或64位,即使在64位模式下)。
添加另一个L
使其成为long long
: 2123123123LL
(64位或以上,从c++ 11开始)。
注意,您只需要为超过int
大小的常量添加后缀。积分转换会产生正确的结果*.
(2123123123LL * 17) // 17 is automatically converted to long long, the result is long long
*但要注意:即使表达式中的单个常量适合int
, 整个操作仍然可以像
(1024 * 1024 * 1024 * 10)
在这种情况下,您应该确保在足够宽的范围内执行算术运算(考虑运算符优先级):
(1024LL * 1024 * 1024 * 10)
-将在64位执行所有3个操作,得到64位的结果。
编辑:文字常量(又称幻数)是不受欢迎的,所以最好的方法是使用符号常量(const int64_t value = 5
)。看看什么是神奇的数字,为什么它不好?了解更多信息。你最好不要读这个答案的其余部分,除非你真的因为一些奇怪的原因想要使用魔法数字。
也可以使用#include <cstdint>
中的intptr_t
和uintprt_t
来让编译器选择是使用int
还是__int64
。
- 将应用程序从32位移植到64位时出现问题
- 如何在 64 位平台上计算 32 位哈希C++?
- 使用 Boost 计算 ECMA-128 64 位 CRC
- 计算 (64 位无符号整数) * (64 位无符号整数) 的商除以 2^64
- C/C++ 在 32 位和 64 位计算机上可执行
- 在 64 位 Linux armv8 计算机上编译 32 位二进制文件时遇到问题
- 64位计算机上的VPTR的大小是否为64位
- 为什么我的编译器在 64 位计算机上运行时使用 8 位字符?
- 64位计算机上的int大小和int指针大小
- 在 x86-64 平台上为 C(++) 中的 64 位无符号参数计算 (a*b)%n FAST
- 64 位 Linux 计算机上的"fftw_malloc"段错误
- 64 位计算机上的 STL 矢量大小
- 如何将具有公共控件的程序从 Visual C++ 6.0 迁移到 Visual C++ 2010(在 64 位计算机上)
- 在64位计算机上进行加密++32位编译
- 算法C/C++:用n和d 32或64位整数计算(2^n)%d的最快方法
- 这个代码如何使用64位乘法和模除法计算字节的奇偶校验
- 在c++中计算64位整数的位数时,大输入(64位)会产生意想不到的结果
- 在64位可执行文件中执行64位计算
- 32 位 64 位 - 警告:右移计数 >= 32 位计算机上的类型宽度
- 64位计算机上的结构填充