8

我有一个应用程序以 s的形式创建唯一IDunsigned long int。应用程序需要这种精度。

但是,我必须在只允许s的协议中发送这些id 。int协议的接收应用程序不需要这种精度。所以我的问题是:如何将 an 转换unsigned long int为 an int,尤其是当 theunsigned long int大于 an时int

编辑:

协议仅支持int. 我很高兴知道如何避免“翻车问题”

发送消息的应用程序需要在很长一段时间内知道唯一性,而接收方只需要在短时间内知道唯一性。

4

6 回答 6

14

这是一种可能的方法:

#include <climits>
unsigned long int uid = ...;
int abbreviated_uid = uid & INT_MAX;

例如,如果int是 32 位,则这将丢弃除 UID 的低 31 位之外的所有位。它只会产生非负值。

这会丢失原始 中的信息uid,但您表示这不是问题。

但是您的问题很模糊,很难判断这是否适合您的目的。

于 2012-07-08T23:01:55.237 回答
3

如您所知,在一般情况下,理论上不能安全地将 an 转换unsigned long int为 an 。int但是,在整数不太大的许多实际案例中确实可以这样做。

我可能会定义和使用这个:

struct Exc_out_of_range {};

int make_int(const unsigned long int a) {
    const int n = static_cast<int>(a);
    const unsigned long int a2 = static_cast<unsigned long int>(n);
    if (a2 != a) throw Exc_out_of_range();
    return n;
}

使用<limits>标头的等效解决方案自然是可能的,但我不知道它是否比上述更好。(如果代码处于时间关键的循环中并且可移植性不是一个因素,那么您可以在汇编中对其进行编码,直接测试感兴趣的位或位,但除非作为汇编语言的练习,否则这将是一个麻烦。)

关于性能,值得注意的是 - 除非您的编译器非常旧 -throw除非使用,否则不会施加运行时负担。

@GManNickG 添加了从std::exception. 我个人对此并没有强烈的感觉,但建议是有根据的和赞赏的,我认为没有理由不遵循它。 您可以在此处阅读有关此类继承的更多信息。

于 2012-07-08T23:18:32.793 回答
3

升压有numeric_cast

unsigned long l = ...;
int i = boost::numeric_cast<int>(l);

如果转换溢出,这将引发异常,这可能是您想要的,也可能不是。

于 2012-07-08T23:46:22.513 回答
3

仅当您需要确保 abbreviated_uid 为非负数时,才需要 Keith Thompson 的“& INT_MAX”。如果这不是问题,并且您可以容忍负 ID,那么一个简单的强制转换(C 风格或 static_cast())就足够了,其好处是if sizeof(unsigned long int)==sizeof(int),那么二进制表示在两端将是相同的(如果您将其转换回unsigned long int接收端,它将与发送端的值相同)。

接收者是否将有关 ID 的响应发送回发送者,原始发送者(现在是响应的接收者)是否需要将其与原始unsigned long intID 匹配?如果是这样,您将需要一些额外的逻辑来将响应与原始 ID 匹配。如果是这样,请发布说明此类要求的编辑,我(或其他人)可以建议解决该问题的方法。该问题的一种可能解决方案是将 ID 分解为多个int部分,并在另一端将其重建为完全相同的unsigned long int值。如果您需要这方面的帮助,我或其他人可以提供帮助。

于 2012-07-08T23:54:07.933 回答
1

我遇到了这个问题,因为我必须有一个解决方案来将较大的整数类型转换为较小的类型,即使可能会丢失信息。

我使用模板想出了一个非常简洁的解决方案:

template<typename Tout, typename Tin>
Tout toInt(Tin in)
{
    Tout retVal = 0;

    if (in > 0)
        retVal = static_cast<Tout>(in & std::numeric_limits<Tout>::max());
    else if (in < 0)
        retVal = static_cast<Tout>(in | std::numeric_limits<Tout>::min());

    return retVal;
}
于 2015-10-19T13:00:52.530 回答
-1

您可以尝试使用std::stringstreamand atoi()

#include <sstream>
#include <stdlib.h>
unsigned long int a = ...;
std::stringstream ss;
ss << a;
std::string str = ss.str();
int i = atoi(str.c_str());
于 2016-09-24T13:31:24.810 回答