在ARM上将uint64_t和long混合使用会产生奇怪的结果

时间:2019-08-22 13:48:50

标签: c++ arm armv7 uint64

在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

import numpy as np
import tensorflow as tf

# Load TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_path="tflite_model.tflite")
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# Test model on random input data.
input_shape = input_details[0]['shape']
input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32)
interpreter.set_tensor(input_details[0]['index'], input_data)

interpreter.invoke()

# The function `get_tensor()` returns a copy of the tensor data.
# Use `tensor()` in order to get a pointer to the tensor.
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

我希望最后两行给出'0'。

在x86上,结果是

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;
}

在Arm(CortexA8)上,结果为

i1       : 31
l2       : 86400000
u2       : 86400000
x - i1*l2: 0
x - i1*u2: 0

1 个答案:

答案 0 :(得分:5)

在这一行代码中:

std::cout << "x - i1*l2: " << x - i1 * l2 << std::endl; // expected '0', got 4294967296

当您将31乘以86400000时,将得到2678400000,即0x9FA52400,它不能适合4个字节的带符号长整数(符号位设置为1)。然后,由于有符号溢出和垃圾值转换为uint64_t以从x减去UB,您将得到UB。在x86上,您显然有更大的long提示,看不到问题所在。