简体   繁体   English

将C ++类型int16_t转换为int64_t,而无需修改基础二进制文件

[英]Convert C++ type int16_t to int64_t without modifying the underlying binary

I am trying to generate a hash code for an object in 3D space so it can be quickly found in an array using a binary search algorithm. 我正在尝试为3D空间中的对象生成哈希码,以便可以使用二进制搜索算法在数组中快速找到它。

Since each object in this array has a unique XYZ location, I figured I could use those three values to generate the hash code. 由于此数组中的每个对象都有一个唯一的XYZ位置,因此我认为可以使用这三个值来生成哈希码。 I used the following code to try and generate the hash code. 我使用以下代码尝试生成哈希代码。

int64_t generateCode(int16_t x, int16_t y, int16_t z) {
    int64_t hashCode = z;//Set Z bits.
    hashCode <<= 16;//Shift them 16 bits.
    hashCode |= y;//Set Y bits.
    hashCode <<= 16;//Shift them 16 bits.
    hashCode |= x;//Set X bits.
}

Now here is the problem from what I can tell. 现在这就是我所知道的问题。 Consider the following peace of code: 考虑以下代码安全性:

int16_t x = -1;
cout << "X: " << bitset<16>(x) << endl;//Prints the binary value of X.
int64_t y = x;//Set Y to X. This will automatically cast the types.
cout << "Y: " << bitset<64>(y) << endl;//Prints the binary value of Y.

The output of this program is as follows: 该程序的输出如下:

X: 1111111111111111
Y: 1111111111111111111111111111111111111111111111111111111111111111

It keeps the numerical value of the number, but changes the underlying binary to do that. 它保留数字的数值,但更改基础二进制文件即可。 I don't want to modify that binary so I can have an output like the following: 我不想修改该二进制文件,因此可以得到如下输出:

X: 1111111111111111
Y: 0000000000000000000000000000000000000000000000001111111111111111

By doing that, I can then create a unique hash code from the XYZ values that would look like the following: 这样,我便可以根据XYZ值创建唯一的哈希码,如下所示:

           Unused            X                 Y                 Z
HashCode: [0000000000000000][0000000000000000][0000000000000000][0000000000000000]

And that will be used for the binary search. 这将用于二进制搜索。

Most compilers will understand and optimize this to do what you actually want: 大多数编译器将理解并优化它以执行您实际想要的操作:

int16_t a[4] = { 0, z, y, x };
int64_t res;
memcpy(&res, a, sizeof(res));

(The compiler will understand that memcpy can be done by a simple 64-bit memory operation, and not actually calling the real memcpy ) (编译器将理解memcpy可以通过简单的64位内存操作来完成,而不是实际调用真正的memcpy

Convert the int16_t to a uint16_t first, then merge them together into a uint64_t that you finally cast to a int64_t : 首先将int16_t转换为uint16_t ,然后将它们合并到uint64_t ,最后将其转换为int64_t

int64_t generateCode(int16_t x, int16_t y, int16_t z) {
    uint64_t hashCode = static_cast<uint16_t>(z);
    hashCode <<= 16;
    hashCode |= static_cast<uint16_t>(y);
    hashCode <<= 16;
    hashCode |= static_cast<uint16_t>(x);
    return static_cast<int64_t>(hashCode);
}

The int16_t / int64_t types will be a two's complement representation (7.20.1.1 paragraph 1 of the C standard requires this), so converting them to a uint*_t of the same size will be a bit-wise no-op. int16_t / int64_t类型将是二进制补码表示形式(C标准的7.2.1.1第1节要求这样做),因此将它们转换为相同大小的uint*_t将是按位无操作的。

Try int64_t y = (uint16_t) x; 尝试int64_t y = (uint16_t) x;

What this does is, it'll make sure the added extra bits are 0 and not 1, since this is unsigned. 这是什么,它将确保添加的额外位是0而不是1,因为这是无符号的。 Make sure you check the sign bit though. 但是请确保您检查符号位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM