【发布时间】:2019-08-22 13:48:50
【问题描述】:
在 uint64_t 和 long 的混合上使用算术会在 arm(c++ 编译器)上产生不需要的结果。相同的代码在 x86 上按预期工作。
如果 long 替换为 uint64_t,它会按预期工作。
Armv7 编译器为 c++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
这里也有代码:http://cpp.sh/2xrnu
int main()
{
uint64_t x = 1000UL * 60 * 60 * 24 * 31;
int i1 = 31;
long l2 = 1000 * 60 * 60 * 24;
uint64_t u2 = 1000 * 60 * 60 * 24;
std::cout << "x : " << x << std::endl;
std::cout << "i1 : " << i1 << std::endl;
std::cout << "l2 : " << l2 << std::endl;
std::cout << "u2 : " << u2 << std::endl;
std::cout << "x - i1*l2: " << x - i1 * l2 << std::endl; // expected '0', got 4294967296
std::cout << "x - i1*u2: " << x - i1 * u2 << std::endl; // expected and got '0'
return 0;
}
我希望最后两行给出 '0'。
在 x86 上,结果是
i1 : 31
l2 : 86400000
u2 : 86400000
x - i1*l2: 0
x - i1*u2: 0
在 Arm (CortexA8) 上,结果是
i1 : 31
l2 : 86400000
u2 : 86400000
x - i1*l2: 4294967296
x - i1*u2: 0
【问题讨论】:
-
这个表达式 1000 * 60 * 60 * 24;具有 int 类型。这个表达式 1000UL * 60 * 60 * 24 * 31;具有 unsigned long 类型。
-
那个平台上的
sizeof(int)和sizeof(long)是什么? -
@vlad-from-moscow 即使我将 1000 * 60 * 60 * 24 更改为 1000L * 60 * 60 * 24,问题仍然存在。而 1000 * 60 * 60 * 24 是 86400000,远低于 int max 吗?
-
31 * 86400000不适合 31 位...您正在从整数溢出中查看 UB。 -
最好
static_cast<uint64_t>()更安全,更易读。