将最小值整数转换为无符号长整数

Convert min value integer to unsigned long

我正在尝试将 整数 的最小值转换为 无符号长整数 ,如下所示:

-2147483648 to 2147483648 第一个值存储在 integer 变量中,第二个是我试图使我的 unsigned long 变量取.

所以我知道如何将 integers -2147483648 的最小值转换为 unsigned int下面:

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

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

但是当我尝试转换为 unsigned long 时,我的输出变成最大 unsigned long 的值我设备上的值 18446744071562067968

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

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

我稍微搜索了一下数据类型及其范围,发现 unsigned long 的范围是
0 to 18446744073709551615,我发现当我们将 整数的最小值 乘以 -1 它不会改变,因为 整数的最大值2147483647,所以它保持 -2147483648,当我把它给不包含那个值的 unsigned long 时,它变成其自身范围的最大值 18446744073709551615.

所以我尝试将-2147483648 * -1的值存储在long int变量中,它的范围是

-9223372036854775808 to 9223372036854775807,所以它可以存储值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"
}

这里我的问题已经解决了,但是这次我想像下面这样进行转换:

int main()
{
     int d = -2147483648;

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

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

但是当我尝试以另一种方式转换它时 unsigned long ul = -(long)(d); 出现了想要的输出 2147483648

所以我的问题是第一种铸造方法和第二种铸造方法之间的区别是什么,为什么它只适用于第二种方式?

你的情况是未定义的行为,因为 d * -12147483648 导致 int 溢出。

为避免这种情况,您需要在操作前将 int 值转换为 long 或 unsigned long 值(正如您在另一个示例中所做的那样)。

这是因为如果在2个int之间进行运算,解决了int变量导致溢出,之后在赋值过程中会强制转换为unsigned long。

你需要提前施法来防止这种情况。

因此,正如剃刀在之前的回答中所说,我需要对 整数 d 进行早期转换,然后将其与 -1 相乘,正如您可以通过这种方式看到的那样:

unsigned long ul = -(long)(d); 或者这样 unsigned long ul = ((long)d) * -1; 它们都是有效的,并且不会导致任何未定义的行为。

但是在这种转换方式中 unsigned long ul = (long)(d * -1); 结果是未定义的行为,为什么?让我们一步步来解释吧。

我们有 (d * -1) 并且它们都是 整数 ,所以当我将 -2147483648 乘以 -1 时,想要的预期输出是 2147483648,但不幸的是 integers 在它的范围内没有这样的值,它会导致未定义的行为,大多数值不会改变,它会保持 -2147483648 即使乘以 -1.

然后我们将未更改的值 -2147483648 转换为 长整数 并且它会保留它,因为它在它的范围内,所以现在的值仍然是 -2147483648,在它之后我们将这个值存储在一个 无符号长整数 中,这里它将是一个未定义的行为,因为我们在 [=46= 中放入一个负数]无符号值。

所以为了避免这个问题,我们要做的就是将 -2147483648 转换为 long 然后乘以 -1 ==> ((long)d) * -1,因为 long 可以存储正值 2147483648 因为它的范围。

然后我们可以将它存储在 unsigned long int 中而不会遇到任何未定义的行为。

这里是有关数据类型范围的更多详细信息的站点:

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