Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does casting change a value's bits in C++?

Tags:

I have a C++ unsigned int which is actually storing a signed value. I want to cast this variable to a signed int, so that the unsigned and signed values have the same binary value.

unsigned int lUnsigned = 0x80000001; int lSigned1 = (int)lUnsigned;                   // Does lSigned == 0x80000001? int lSigned2 = static_cast<int>(lUnsigned);      // Does lSigned == 0x80000001? int lSigned3 = reinterpret_cast<int>(lUnsigned); // Compiler didn't like this 

When do casts change the bits of a variable in C++? For example, I know that casting from an int to a float will change the bits because int is twos-complement and float is floating-point. But what about other scenarios? I am not clear on the rules for this in C++.

In section 6.3.1.3 of the C99 spec it says that casting from an unsigned to a signed integer is compiler-defined!

like image 576
sourcenouveau Avatar asked Nov 18 '10 18:11

sourcenouveau


People also ask

What happens when casting in C?

Type casting refers to changing an variable of one data type into another. The compiler will automatically change one type of data into another if it makes sense. For instance, if you assign an integer value to a floating-point variable, the compiler will convert the int to a float.

Does casting truncate?

When casting from a float or numeric to an integer, the CAST function will truncate the result. For other conversions, the CAST function will round the result.

Why is typecasting required in malloc function?

The malloc function returns a pointer value of type void* . A value of that type can be implicitly converted to any object pointer type. No cast is necessary, and in some cases using a cast can mask errors.

What is pointer type casting in C?

In the C language, casting is a construct to view a data object temporarily as another data type. When you cast pointers, especially for non-data object pointers, consider the following characteristics and constraints: You can cast a pointer to another pointer of the same IBM® i pointer type.


2 Answers

A type conversion can

  • keep the conceptual value (the bitpattern may have to be changed), or

  • keep the bitpattern (the conceptual value may have to be changed).

The only C++ cast that guaranteed always keeps the bitpattern is const_cast.

A reinterpret_cast is, as its name suggests, intended to keep the bitpattern and simply reinterpret it. But the standard allows an implementation very much leeway in how to implement reinterpret_cast. In some case a reinterpret_cast may change the bitpattern.

A dynamic_cast generally changes both bitpattern and value, since it generally delves into an object and returns a pointer/reference to a sub-object of requested type.

A static_cast may change the bitpattern both for integers and pointers, but, nearly all extant computers use a representation of signed integers (called two's complement) where static_cast will not change the bitpattern. Regarding pointers, suffice it to say that, for example, when a base class is non-polymorphic and a derived class is polymorphic, using static_cast to go from pointer to derived to pointer to base, or vice versa, may change the bitpattern (as you can see when comparing the void* pointers). Now, integers...

With n value bits, an unsigned integer type has 2^n values, in the range 0 through 2^n-1 (inclusive).

The C++ standard guarantees that any result of the type is wrapped into that range by adding or subtracting a suitable multiple of 2^n.

Actually that's how the C standard describes it; the C++ standard just says that operations are modulo 2^n, which means the same.

With two's complement form a signed value -x has the same bitpattern as the unsigned value -x+2^n. That is, the same bitpattern as the C++ standard guarantees that you get by converting -x to unsigned type of the same size. That's the simple basics of two's complement form, that it is precisely the guarantee that you're seeking. :-)

And nearly all extant computers use two's complement form.

Hence, in practice you're guaranteed an unchanged bitpattern for your examples.

like image 119
Cheers and hth. - Alf Avatar answered Oct 09 '22 09:10

Cheers and hth. - Alf


If you cast from a smaller signed integral type to a larger signed integral type, copies of the original most significant bit (1 in the case of a negative number) will be prepended as necessary to preserve the integer's value.

If you cast an object pointer to a pointer of one of its superclasses, the bits can change, especially if there is multiple inheritance or virtual superclasses.

You're kind of asking for the difference between static_cast and reinterpret_cast.

like image 34
Mike DeSimone Avatar answered Oct 09 '22 11:10

Mike DeSimone