在64位机器上,C语言中的long long和long具有相同的范围吗?

5
我在 /usr/include/limits.h 中看到了这个:
/* Minimum and maximum values a `signed long int' can hold.  */
if __WORDSIZE == 64
 define LONG_MAX     9223372036854775807L
else
 define LONG_MAX     2147483647L
endif
define LONG_MIN      (-LONG_MAX - 1L)
/* Maximum value an `unsigned long int' can hold.  (Minimum is 0.)  */
if __WORDSIZE == 64
 define ULONG_MAX    18446744073709551615UL
else
 define ULONG_MAX    4294967295UL
endif
ifdef __USE_ISOC99

/* Minimum and maximum values a `signed long long int' can hold.  */
define LLONG_MAX    9223372036854775807LL
define LLONG_MIN    (-LLONG_MAX - 1LL)

/* Maximum value an `unsigned long long int' can hold.  (Minimum is 0.)    */
 define ULLONG_MAX   18446744073709551615ULL

看起来 unsigned long long intunsigned long int 的最大值都是18446744073709551615……

这是否意味着在这台机器上 long longlong 是相同的? 如果确实如此,那么我们为什么要有单独的 long long 说明符?

从阅读 C 语言书籍上来看,我预期 long long 的大小应该是 long 的两倍。 我错了吗? (但是我同意标准规定 int >= short intlong >= int,但很难理解 long long >= long。)


5
那是否意味着,在这台机器上 long long 和 long 的意思相同?那为什么我们还有一个单独的 long long 类型标识符呢?嗯,因为你的机器不是地球上唯一的机器。 - mathieu
嗯...我认为在所有的Linux 64位机器上都是一样的(在Windows上可能会有所不同)...你也检查一下吧? - Harish Kayarohanam
1
请参阅64位Windows上的long位大小是多少? 在这样的机器上,long longlong更大。在您的机器上,这两种类型的大小相同。两者都是完全有效的 - 习惯就好了。 - Jonathan Leffler
1
可以设计和构建一个编译器,支持 CHAR_BIT == 8sizeof(short) == 2sizeof(int) == 4sizeof(long) = 8sizeof(long long) == 16(也称为128位)和 sizeof(intmax_t) == 32(也称为256位)。之后,您将无法使用标准名称来表示不同大小的整数,除非使用数字 int64_t 风格的名称。 - Jonathan Leffler
唯一真正确定的是 sizeof( long long ) >= sizeof( long ) >= sizeof( int ) >= sizeof( short ) >= sizeof( char )。请参阅 C 标准的 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf。 - Andrew Henle
显示剩余2条评论
3个回答

6
C语言规范指定了符合规范的实现必须提供的类型。从标准的第一个版本开始,类型long [int]就在其中之一,自C99以来,类型long long [int]也在其中之一。
标准指定了各种整数类型的大小关系,特别是指出了类型long long必须能够表示类型long可以表示的所有值,但它留下了许多类型特征“实现定义”的方面,这意味着实现可以选择(并且有义务记录他们的选择)。其中这些特征包括是否存在超出long范围的任何long long值。
在标准的层面上,这与实现目标机器的本地字长没有直接关系,但实现可以将其作为选择类型表示的标准之一。
如果您关心所使用的各种类型可以表示的值的范围,请使用stdint.h中的固定宽度类型(如int64_tuint32_t等),或者使用给出整数类型限制的标准宏(例如INT_MAX和朋友们)。

4

C有两种整数类型:

  • 传统类型:short、int、long和long long。每个实现都可以定义这些类型的大小。C只规定sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)(参考C1X的final draft of C1X)。使用这些类型时,你永远无法确定哪个是32位或64位,因为它明确取决于实现。
  • 显式类型:int8_t、int16_t、int32_t、int64_t - 当它们存在时,你可以确定它们的大小。标准说它们应该在stdint.h中声明,但不幸的是,它们都是可选的 - 这意味着即使所有主要实现支持int16_t、int32_t和int64_t(参见上述草案的7.20和7.20.1.1),你也不能确定它们是否存在。

同时...传统类型和显式类型之间没有推荐的关系(请注意,传统显式这些称呼是我自己起的)。

同一草案的7.20.1定义了其他有趣的类型:

  • intptr_tuintptr_t:分别是有符号和无符号整数类型,保证足够大以容纳指针(不幸的是,这些类型是可选的...)
  • int_leastX_t:至少X位的类型
  • int_fastX_t:至少X位的最快类型

以下类型是必需的(意味着它们应该存在于任何符合规范的实现中):

int_least8_t int_least16_t int_least32_t int_least64_t uint_least8_t uint_least16_t uint_least32_t uint_least64_t

int_fast8_t int_fast16_t int_fast32_t int_fast64_t uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t

  • intmax_tuintmax_t: 有符号(或无符号)整数类型,能够表示任何有符号(或无符号)整数类型的任何值 - 必需

没有提到“最小”或“最快”的显式类型吗? - Jonathan Leffler
@JonathanLeffler:虽然OP没有明确要求,但我必须承认现在的答案更加完整了。 - Serge Ballesta
遗憾的是,通过涵盖额外的类型,它不能像之前那样简洁(你要涵盖两倍的类型),但是(正如你所指出的)“最小”和“最快”的类型是可靠存在的(不像精确类型),因此具有价值。 - Jonathan Leffler

3
你问道:

那么这是否意味着,在这台机器上long long和long是同样的意思?

即使它们的大小相同,类型名称也是不同的。

那么,为什么我们还要有一个单独的long long指定符?

语言将它们规定为不同的类型。支持它们所使用的整数数字的大小取决于平台。在你正在使用的编译器中,long long和long的大小相同。但在同一平台上的不同编译器中,long long可以使用64位,而long和int只能使用32位。


哎呀,但是在这里long long类型并不适用? - Harish Kayarohanam
好的,我的疑惑是,如果系统的位大小如此不同,可能是64位和32位,也可能是Windows和Linux,那么编写能够在所有地方运行的软件不是很困难吗? - Harish Kayarohanam
1
@HarishKayarohanam,如果您正在编写一个专门针对此平台的程序,则使用long long不会给您带来任何优势。如果您有兴趣编写一个可移植到另一个平台的程序,在那里使用最大尺寸的long long将是一个优势,那么您可以使用long long - R Sahu
@HarishKayarohanam,你正在把它转化为聊天 :) - R Sahu

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