在 ARM 上混合使用 uint64_t 和 long 会产生奇怪的结果
Mixing uint64_t and long on ARM produces strange results
对 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
在这行代码中:
std::cout << "x - i1*l2: " << x - i1 * l2 << std::endl; // expected '0', got 4294967296
当您将 31 乘以 86400000 时,您会得到 2678400000,即 0x9FA52400,它不适合 4 字节的有符号长整数(符号位设置为 1)。然后你得到 UB 由于有符号溢出和垃圾值转换为 uint64_t
以从 x 中减去它。在 x86 上你显然有更大的 long
hense 你没有看到这个问题。
对 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
在这行代码中:
std::cout << "x - i1*l2: " << x - i1 * l2 << std::endl; // expected '0', got 4294967296
当您将 31 乘以 86400000 时,您会得到 2678400000,即 0x9FA52400,它不适合 4 字节的有符号长整数(符号位设置为 1)。然后你得到 UB 由于有符号溢出和垃圾值转换为 uint64_t
以从 x 中减去它。在 x86 上你显然有更大的 long
hense 你没有看到这个问题。