为什么我们将INT_MIN定义为-INT_MAX - 1?

9
据我所知,这是一个标准的“习语”。
#  define INT_MIN   (-INT_MAX - 1)  
#  define INT_MAX   2147483647    

问题:为什么INT_MIN的定义不是-2147483648?


4
如果你将它们分别定义,当你想进行修改时,你必须提醒自己同时更改两个。如果其中一个依赖于另一个,则只需更改一个,更改将应用于两者。 - Jason Hu
@HuStmpHrrr:我看到有一个原因,但没有解释那个原因(与编译器有关而不是代码设计)。 - Cratylus
不幸的是,我目前没有gcc。但我认为你可以直接尝试int foo = -2147483648;,看看编译器是否会报错。我很好奇结果如何。 - Jason Hu
1
我不太喜欢将其标记为“可能重复”时立即被盖上“重复”的印章。但无论如何,这个问题以前已经被问过很多次了。 - AnT stands with Russia
@AndreyT 我同意。虽然授予我们这些足够疯狂的人构建高声望的insta-dupe的权力很好,但我更希望他们能给我们一个选项,作为备选方案,如果我们认为它是重复的,但想要我们的会员支持。我不认为这是一个难添加的功能。也许可以在meta上讨论一下。 - WhozCraig
1个回答

17

因为2147483648是一个long值,因为它不能适应int(在32位int和64位long的常用系统中,在32位long的系统中,它是long long类型)。所以-2147483648long类型,而不是int类型。

请记住,在C语言中,无后缀的十进制整数常量是第一种类型intlonglong long,其可以表示。

同样,在C语言中,-2147483648不是整数常量;2147483648是整数常量。 -2147483648是由一元运算符-和整数常量2147483648形成的表达式。

编辑:如果您还没有被说服-2147483648不是int类型(评论中有些人仍然怀疑),您可以尝试打印这个:

printf("%zu %zu\n", sizeof INT_MIN, sizeof -2147483648);

您很可能会得到以下内容:
4 8

在常见的32位和64位系统上。

另外,为了遵循一个评论,我谈论的是最近的C标准:使用c99或c11方言进行测试。c89规则的十进制整数常量不同:-2147483648在c89中是unsigned long类型。实际上,在c89中(在c99中不同,请参见上文),未附后缀的十进制整数常量的类型是intlongunsigned long

编辑2@WhozCraig提供了另一个示例(但是针对C++),以显示-2147483648不是int类型。

以下示例虽然是在C++中,但是强调了这一点。它使用32位架构的g++编译。请注意从传递的参数推导中获取的类型信息:

#include <iostream>
#include <climits>

template<typename T>
void foo(T value)
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
    std::cout << value << '\n';
}

int main()
{
    foo(-2147483648);
    foo(INT_MIN);
    return 0;
}

输出

void foo(T) [T = long long]
-2147483648
void foo(T) [T = int]
-2147483648

3
更重要的是,单目负号应用于一个已经由值确定类型的表达式。在32位系统上,将2147483648作为值(在应用单目负号之前)赋给int类型是不可表示的。 - WhozCraig
3
我认为这不是OP所问的,因为INT_MIN是使用INT_MAX定义的,OP想知道为什么INT_MIN没有使用常量(如INT_MAX)来定义。 - Invalid
2
@ouah: 因为2147483648是一个长整型数值,因此不适合作为int类型使用。但是数字-2147483648是int类型范围的一部分。 - Cratylus
1
@Cratylus -2147483648 不是整数常量。2147483648 是整数常量。-2147483648 是带有一元负号操作的整数常量 2147483648 - ouah
@ouah “你最有可能得到的结果是:4 8” - http://codepad.org/9TVJMzIu - kotlomoy
显示剩余17条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接