c++ - 将 ulong 转换为 long

标签 c++ bit-manipulation endianness

我有一个数字存储为 ulong。我希望存储在内存中的位以 2 的补码方式解释。所以我希望第一位是符号位等。如果我想转换为 long,以便该数字被正确解释为 2 的补码,我该怎么做?

我尝试创建不同数据类型的指针,它们都指向同一缓冲区。然后我将 ulong 存储到缓冲区中。然后我取消引用一个长指针。但这给了我一个不好的结果?

我做到了:

#include <iostream>
using namespace std;

int main() {
    unsigned char converter_buffer[4];//  

    unsigned long       *pulong;
    long                *plong;


    pulong = (unsigned long*)&converter_buffer;
    plong  =  (long*)&converter_buffer;

    unsigned long ulong_num = 65535; // this has a 1 as the first bit

    *pulong = ulong_num;

    std:: cout << "the number as a long is" << *plong << std::endl;
    return 0;
}

出于某种原因,这给了我相同的正数。 选角会有帮助吗?

最佳答案

实际上使用指针是一个好的开始,但您必须先将 unsigned long* 转换为 void*,然后才能将结果转换为 long* 并取消引用它:

#include <iostream>
#include <climits>

int main() {
    unsigned long ulongValue = ULONG_MAX;
    long longValue = *((long*)((void*)&ulongValue));

    std::cout << "ulongValue: " << ulongValue << std::endl;
    std::cout << "longValue:  " << longValue << std::endl;

    return 0;
}

上面的代码将产生以下结果:

ulongValue: 18446744073709551615
longValue:  -1

使用模板,您可以使其在代码中更具可读性:

#include <iostream>
#include <climits>

template<typename T, typename U>
T unsafe_cast(const U& from) {
    return *((T*)((void*)&from));
}

int main() {
    unsigned long ulongValue = ULONG_MAX;
    long longValue = unsafe_cast<long>(ulongValue);

    std::cout << "ulongValue: " << ulongValue << std::endl;
    std::cout << "longValue:  " << longValue << std::endl;

    return 0;
}

请记住,此解决方案绝对不安全,因为您可以将任何内容转换为 void*。这种做法在 C 中很常见,但我不建议在 C++ 中使用它。考虑以下情况:

#include <iostream>

template<typename T, typename U>
T unsafe_cast(const U& from) {
    return *((T*)((void*)&from));
}

int main() {
    std::cout << std::hex << std::showbase;

    float fValue = 3.14;
    int iValue = unsafe_cast<int>(fValue); // OK, they have same size.

    std::cout << "Hexadecimal representation of " << fValue
              << " is: " << iValue << std::endl;
    std::cout << "Converting back to float results: "
              << unsafe_cast<float>(iValue) << std::endl;

    double dValue = 3.1415926535;
    int lossyValue = unsafe_cast<int>(dValue); // Bad, they have different size.

    std::cout << "Lossy hexadecimal representation of " << dValue
              << " is: " << lossyValue << std::endl;
    std::cout << "Converting back to double results: "
              << unsafe_cast<double>(lossyValue) << std::endl;

    return 0;
}

上面的代码对我来说结果如下:

Hexadecimal representation of 3.14 is: 0x4048f5c3
Converting back to float results: 3.14
Lossy hexadecimal representation of 3.14159 is: 0x54411744
Converting back to double results: 6.98387e-315

最后一行你可以获得任何东西,因为转换将从内存中读取垃圾。

编辑

lorro下面评论说,使用memcpy()更安全,可以防止溢出。因此,这是类型转换的另一个版本,它更安全:

template<typename T, typename U>
T safer_cast(const U& from) {
    T to;
    memcpy(&to, &from, (sizeof(T) > sizeof(U) ? sizeof(U) : sizeof(T)));
    return to;
}

关于c++ - 将 ulong 转换为 long,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43526910/

相关文章:

java - 反转 32 位无符号整数的位

c# - 需要一个先升后降的快速函数,使用按位运算

c++ - 按位操作函数

c++ - Big Endian 字节与字符串作为字符串中的键 - 字符串数据库

c# - 如何使用 C# 将大端发送到网络流

C++ 和 DLL 未在此范围内声明

android - Qt 无法在 Android 模拟器上绘制

c++ - c++ 单例在使用互斥锁时是否需要内存屏障?

c++ - 为什么我的 TCP 传输在 cygwin 上损坏了?

C++ regex_match 不匹配