为什么最小的int,-2147483648,类型是'long'?

这个问题在这里已经有了答案:

  • 为什么是0 <-0x80000000? 6个答案
  • (-2147483648> 0)在C ++中返回true? 4个答案

  • 在C中, -2147483648不是整数常量。 2147483648是一个整数常量,并且-只是一个应用于它的一元运算符,产生一个常量表达式。 2147483648的值不适合int (它太大了, 2147483647通常是最大的整数),因此整数常量的类型为long ,这会导致您观察到的问题。 如果您想提到int下限,请使用<limits.h>的宏INT_MIN (便携式方法)或小心避免提及2147483648

    printf("PRINTF(d) t: %dn", -1 - 2147483647);
    

    问题是-2147483648不是一个整数字面量。 它是由一元否定运算符组成的表达式-以及整数2147483648 ,如果int s是32位,则该整数太大而不能成为int 。 由于编译器会在应用否定运算符之前选择适当大小的有符号整数来表示2147483648 ,因此结果的类型将大于int

    如果你知道你的int是32位,并且想避免这个警告而不会破坏可读性,那么使用明确的强制转换:

    printf("PRINTF(d) t: %dn", (int)(-2147483648));
    

    这是在具有32位int的二进制补码机器上定义的行为。

    为了提高理论的可移植性,请使用INT_MIN而不是数字,并让我们知道您找到一台非2的补充机器来测试它。


    要清楚的是,最后一段在一定程度上是一个笑话。 如果你的意思是“最小的int ”, INT_MIN肯定是要走的路,因为int大小各不相同。 例如,仍然有很多16位实现。 写出-231只有在你明确指出这个值时才有用,在这种情况下,你可能会使用一个固定大小的类型,比如int32_t而不是int

    您可能需要一些替代方法来写出十进制数字,以便让那些可能不会注意到21474836482174483648之间差异的人更清楚,但您需要小心。

    如上所述,在一个32位2的补码机上, (int)(-2147483648)不会溢出,因此定义良好,因为-2147483648将作为更宽的带符号类型进行处理。 但是, (int)(-0x80000000)0x80000000将被视为一个unsigned int (因为它符合无符号表示); -0x80000000被良好定义(但-如果没有效果int是32位),并且将所得的转化unsigned int 0x80000000int涉及溢出。 为避免溢出,您需要将十六进制常量转换为带符号的类型: (int)(-(long long)(0x80000000))

    同样,如果你想使用左移操作符,你需要小心。 1<<31在具有32位(或更小) int的32位机器上未定义行为; 如果int至少为33位,它只会计算为231,因为如果k严格小于左边参数的整数类型的非符号位数,那么左移k位是很好的定义。

    1LL<<31是安全的,因为long long int必须能够表示263-1,所以它的位大小必须大于32.因此,表单

    (int)(-(1LL<<31))
    

    可能是最可读的。 因人而异。


    对于任何传球的学生,这个问题被标记为C,并且最新的C草案(n1570.pdf)针对E1 << E2 ,其中E1具有带符号类型,该值仅在E1是非负的情况下定义并且E1 × 2E2 “可以在结果类型中表示”。 (第6.5.7段第4段)。

    这是从C ++,其中如果左移位运算符的应用定义的不同E1非负和E1 × 2E2 “是在相应的无符号类型的结果类型的表示的”(§5.8第2段,强调)。

    在C ++中,根据最新的草案标准,如果值不能在目标类型中表示(§4.7第3段),则根据最新草案标准,将整数值转换为有符号整数类型是实现定义的。 C标准的相应段落 - 第6.3.1.3段。 3 - 表示“结果是实现定义的或者实现定义的信号被提升”)。

    链接地址: http://www.djcxy.com/p/73279.html

    上一篇: Why does the smallest int, −2147483648, have type 'long'?

    下一篇: What is the rationale for this undefined behavior?