Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: How do I cast an int to an unsigned long and not change any bits?

C++: How do I cast an int to an unsigned long and not change any bits? I want to pack and unpack values into memory. The word size is 64 bits.

This snippet illustrates the problem:

int v1 = -2; // 0xfe
unsigned long v2=(unsigned long)v1; // 0xfffe, I want 0x00fe

The simple solution is:

unsigned long v2=(unsigned int)v1; // 0x00fe

However, this code is in a template where the target type is a parameter, so I had to resort to this:

uint64 target = mem[index] & mask;
uint64 v;
if (value < 0) {
    switch (bits) {
    case 8:
        v = (uint8)value;
        break;
    case 16:
        v = (uint16)value;
        break;
    case 32:
        v = (uint32)value;
        break;
    }
} else {
    v = value;
}
v = v << lShift;
target |= v;
mem[index] = target;

Assume, for example, the type for "value" is an int (16 bits) and bits=16. The goal is to mask the bits in memory for value and replace them.

Does anyone know an easier way?

like image 678
Michael Fitzpatrick Avatar asked Aug 05 '11 23:08

Michael Fitzpatrick


People also ask

What happens when you cast an int to an unsigned int?

You can convert an int to an unsigned int . The conversion is valid and well-defined. Since the value is negative, UINT_MAX + 1 is added to it so that the value is a valid unsigned quantity. (Technically, 2N is added to it, where N is the number of bits used to represent the unsigned type.)

What happens when you cast signed to unsigned in C?

Conversion from signed to unsigned does not necessarily just copy or reinterpret the representation of the signed value. Quoting the C standard (C99 6.3. 1.3): When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

How many bits is a unsigned long int in C?

An unsigned data type stores only positive values. It takes a size of 64 bits. A maximum integer value that can be stored in an unsigned long long int data type is 18, 446, 744, 073, 709, 551, 615, around 264 – 1(but is compiler dependent).

How do I cast unsigned int?

To convert a signed integer to an unsigned integer, or to convert an unsigned integer to a signed integer you need only use a cast. For example: int a = 6; unsigned int b; int c; b = (unsigned int)a; c = (int)b; Actually in many cases you can dispense with the cast.


2 Answers

Assuming you have C++0x support:

#include <type_traits>
v= static_cast<std::make_unsigned<decltype(value)>::type>(value);

I'm assuming that you are parameterizing on the type of value, otherwise this doesn't make any sense.

EDIT: making it more C++-ish by using static_cast instead of a C cast. I suppose that's what got me a downvote.

like image 155
MSN Avatar answered Oct 12 '22 19:10

MSN


If you don't mind the typing, a trait class comes to mind:

template <typename IType> struct ToULong;

template <> struct ToULong<signed char>
{
  static inline unsigned long int get(signed char c) { return (unsigned char)(c); }
};

template <> struct ToULong<signed short int>
{
  static inline unsigned long int get(signed short int c) { return (unsigned short int)(c); }
};

/* ... signed int, signed long int, signed long long int ... */

Usage:

template <typename IType>
struct Foo
{
  unsigned lont int get_data() const { return ToULong<IType>::get(m_data); }
private:
  IType m_data;
}

Update: Even simpler, you could just make a bunch of overloads:

unsigned long int toULong(            char c) { return (unsigned      char)(c); }
unsigned long int toULong(signed      char c) { return (unsigned      char)(c); }
unsigned long int toULong(signed short int c) { return (unsigned short int)(c); }
unsigned long int toULong(signed       int c) { return (unsigned       int)(c); }
unsigned long int toULong(signed  long int c) { return (unsigned  long int)(c); }

2nd update: You should probably say static_cast<T>(x) rather than (T)(x) if you want to be even more C++-like.

like image 29
Kerrek SB Avatar answered Oct 12 '22 21:10

Kerrek SB