【问题标题】:Why are there differing definitions of INT64_MIN? And why do they behave differently?为什么 INT64_MIN 有不同的定义?为什么他们的行为不同?
【发布时间】:2012-07-01 11:23:56
【问题描述】:

我公司的stdint.h 标题为:

#define INT64_MIN -9223372036854775808LL

但在我项目的一些代码中,一位程序员写道:

#undef INT64_MIN
#define INT64_MIN (-9223372036854775807LL -1)

然后他在代码中使用了这个定义。
项目编译时没有警告/错误。
当我试图删除他的定义并使用默认定义时,我得到了:

error: integer constant is so large that it is unsigned

这两个定义似乎是等价的。
为什么一个编译好而另一个编译失败?

【问题讨论】:

  • 标准头文件中的#define导致错误是不是有点吓人?
  • @fvu:没关系,事实证明问题只是 abelenky 的雇主用他们自己的损坏版本替换了标准标题(见下面的 cmets)。
  • @SteveJessop 我在讨论中看到了这对我来说似乎是一个非常愚蠢的想法。
  • 这能回答你的问题吗? Why do we define INT_MIN as -INT_MAX - 1?

标签: c gcc 64-bit min


【解决方案1】:

-9223372036854775808LL 不是单个文字。它是一个由应用于常量9223372036854775808LL 的一元- 运算符组成的表达式。

该常量(几乎)超出了long long 类型的范围,这会导致警告。 (我假设 long long 是 64 位,几乎可以肯定是。)

另一方面,表达式(-9223372036854775807LL -1) 包含在long long 范围内的文字,并且是同样INT64_MIN 更有效的定义,因为它属于正确的类型(正如 Steve Jessop 在评论中指出的那样)。

【讨论】:

  • 很好的解释。这是否意味着 stdint.h 中的定义是错误的,因为它使用了 LL 范围之外的值?
  • @abelenky:不一定。只要它为要与它一起使用的编译器提供正确的行为,就可以了。即使它产生了一个虚假的警告,也不会使它不符合要求——尽管我仍然认为这是一个错误。请注意,我系统上的<stdint.h> 使用-1 技巧。你在什么系统上,你的<stdint.h>来自哪里?
  • 我使用的是 64 位 Linux 系统。 stdint.h 来自公司源代码库。我倾向于假设它有一些 Unix 背景,但不知道它的历史细节。
  • @abelenky:为什么贵公司提供自己的<stdint.h>?它应该由您的编译器或运行时库提供。在任何 Linux 系统上,它都是由 glibc 提供的。
  • @Keith:C99 的 7.18.2 提到 INT64_MIN,“该表达式应具有与根据整数提升转换为相应类型的对象的表达式相同的类型”。所以你的定义比提问者的雇主的定义更有效,而不是同样有效:INT64_MIN 的类型必须int64_t,而不是uint64_t。如果有人写了if (INT64_MIN > 0) ...,则类型错误的表达式对于要使用的编译器来说不能具有正确的行为。但在许多/大多数编译器上,((long long)-922 etc) 就可以了。
猜你喜欢
  • 2018-03-28
  • 2020-04-27
  • 1970-01-01
  • 2012-11-07
  • 2014-01-13
  • 1970-01-01
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
相关资源
最近更新 更多