简体   繁体   中英

Convert min value integer to unsigned long

I am trying to convert the min value of integers to an unsigned long , like the following:

-2147483648 to 2147483648 the first value which is stored in the integer variable, and the second is the value that I'm trying to make my unsigned long variable takes.

So I know how to convert the min value of integers -2147483648 to unsigned int as it appears in the main below :

int main()
{
    int d = -2147483648;
    unsigned int u = (d * -1);              

    printf("%u\n", u);                             //the output is "2147483648"
}

but when I'am trying to do the same with converting to unsigned long my output becomes the value of the max unsigned long value which is on my device 18446744071562067968

int main()
{
    int d = -2147483648;
    unsigned long ul = (d * -1);              

    printf("%lu\n", ul);                             //the output is "18446744071562067968"
}

I searched a little bit about Data Types and their ranges, and I saw that the range of unsigned long is
0 to 18446744073709551615 , and I figured that when we multiply the min value of integers with -1 it doesn't change because the max value of integers is 2147483647 , so it stays -2147483648 , and when I give it to the unsigned long which doesn't contain that value, it becomes the max value of its own range 18446744073709551615 .

So I tried to store the value of -2147483648 * -1 in long int variable, which its range is

-9223372036854775808 to 9223372036854775807 , so it can store the value 2147483648 .

int main()
{
     int d = -2147483648;
     long int l = d;                 // l now contains -2147483648

     l *= -1;                        // now it becomes 2147483648

     unsigned long ul = l;           // now we managed to store 2147483648 in unsigned long variable

     printf("%ld\n", ul)             //the output is "2147483648"
}

And here my problem is solved, but I wanted to do it with casting this time like the following :

int main()
{
     int d = -2147483648;

     unsigned long ul = (long)(d * -1);          

     printf("%lu\n", ul)             //the output is "18446744071562067968" :(
}

But when I try to cast it in another way unsigned long ul = -(long)(d); the wanted output 2147483648 appears.

so my question is what the difference between the first casting and the second casting method and why it worked just with the second way?

You case is an undefined behaviour because d * -1 is 2147483648 that cause overflow for an int.

To avoid this you need to cast before the operation the int value to a long or unsigned long value (as you have alredy done in the other example).

This because if the operation is done between 2 int, it was solved in int variable and cause overflow, after that in the assignement procedure it will be casted to unsigned long.

You need to prevent this with an early cast.

So as razor said in the previous answer, I need to do an early cast to the integer d , and then multiply it with -1 , as you can see in this way :

unsigned long ul = -(long)(d); or this way unsigned long ul = ((long)d) * -1; they are both valid and it`ll not result any undefined behavior.

but in this casting way unsigned long ul = (long)(d * -1); the result is undefined behavior, why? let's explain it step by step.

we have (d * -1) and both of them are integers , so when I multiply -2147483648 by -1 the wanted expected output is 2147483648 , but unfortunately integers doesn't have such a value in it's range, and it'll result an undefined behavior, mostly the value will not change and it'll stay -2147483648 even after multiplying it with -1 .

then we cast the unchanged value, which is -2147483648 to long integer and it'll hold it because it has it in it's range, so the value now still -2147483648 , after it we store this value in an unsigned long integer and here it'll be an undefined behavior, because we are putting a negative number in unsigned value.

so to avoid this problem all what shall we do is to cast -2147483648 to long then multiply it with -1 ==> ((long)d) * -1 , because long can store the positive value 2147483648 due it's range.

and then we can store it in the unsigned long int without facing any undefined behavior.

here is a site for more details about data types range :

https://www.tutorialspoint.com/cprogramming/c_data_types.htm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM