How can I safely convert `unsigned long int` to` int`?

I have an application that creates unique identifiers in the form of unsigned long ints. The application needs such accuracy.

However, I need to send these identifiers to a protocol that only allows ints. The receiving application — the protocol — does not need this accuracy. So my questions are: how to convert unsigned long intto int, especially when unsigned long intmore than int?

edit:

protocol supports only int. I would be happy to know how to avoid the "transition problems"

The application sending the message must know uniqueness for a long period of time, while the receiver must know uniqueness only for a short period of time.

+5
source share
6 answers

Here is one possible approach:

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

If it intis 32 bits, for example, it discards everything except the 31 bits of the least significant bit of the UID. It will give only non-negative values.

This loses information from the original uid, but you indicated that this is not a problem.

But your question is vague enough that it’s hard to say whether this will fit your goals.

+8
source

Boost has numeric_cast:

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

This will throw an exception if the conversion overflows, which may or may not be what you want.

+3
source

Keith Thompson & INT_MAX " , , abbreviated_uid . , , (C-style static_cast()), , , sizeof(unsigned long int)==sizeof(int), ( unsigned long int , , ).

, ( ) unsigned long int? , . , , ( ) . ID int unsigned long int . , - .

+3

, unsigned long int 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 adds advice for inheriting from std::exception. I personally do not have strong feelings about this, but the advice is justified and appreciated, and I see no reason not to follow it. Here you can learn more about such inheritance.

+2
source

I came to this because I had to have a solution for converting large integer types to smaller types, even when information was potentially lost.

I came up with a pretty neat solution using templates:

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;
}
+1
source

You can try using 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());
-1
source

All Articles