在C++中,int和long有什么区别?

133

如果我错了,请纠正我,

int类型占用4个字节,取值范围为-2,147,483,648到2,147,483,647(2的31次方)
long类型占用4个字节,取值范围为-2,147,483,648到2,147,483,647(2的31次方)

C++中有什么区别吗?它们可以互换使用吗?


在我的运行于32位处理器的VS2005中,int类型默认大小为4个字节。 - user436960
3
相关问题:long类型保证至少有32位吗? - John Dibling
如果您想编写可移植的代码,请考虑使用 #include <stdint.h> 和指定大小的类型,例如 uint32_t。在新平台上,您只需要确保 stdint.h 对于该特定平台正确即可,这样您的代码就能按照预期工作。 - BitTickler
9个回答

119

这是实现相关的。例如,在Windows下它们是相同的,但在Alpha系统上,long为64位而int为32位。这篇文章涵盖了Intel C++编译器在不同平台上变量规则。总结一下:

  OS           arch           size
Windows       IA-32        4 bytes
Windows       Intel 64     4 bytes
Windows       IA-64        4 bytes
Linux         IA-32        4 bytes
Linux         Intel 64     8 bytes
Linux         IA-64        8 bytes
Mac OS X      IA-32        4 bytes
Mac OS X      Intel 64     8 bytes  

我认为我们应该考虑将这个答案(一个示例答案)与有关C++标准的一些详细信息结合起来。 C++0x的草案可在http://open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf中找到,并且已经标记,因此您可以看到它与上一个版本之间的差异。 - Patrick Johnmeyer
包括一些关于类型大小顺序的信息,比枚举不同平台的大小提供了更多的信息 - 正如@Kevin所说那样。 (-1票) - xtofl
2
一些编译器甚至有标志,允许您修改int和long的默认大小,即强制它们为8或16等。有关详细信息,请参阅您的编译器文档。 - Martin York
7
注意,这些是长尺寸的尺寸。 - rogerdpack
1
请同时包括 int 的大小。 - cegprakash
gcc的一个出色特性是,即使“int”和“long”具有相同的表示形式,这也不意味着“int *”可以更新“long”,或者“long ”可以更新“int”,即使指针通过void进行转换。 - supercat

84

你所拥有的唯一保证是:

sizeof(char) == 1
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

// FROM @KTC. The C++ standard also has:
sizeof(signed char)   == 1
sizeof(unsigned char) == 1

// NOTE: These size are not specified explicitly in the standard.
//       They are implied by the minimum/maximum values that MUST be supported
//       for the type. These limits are defined in limits.h
sizeof(short)     * CHAR_BIT >= 16
sizeof(int)       * CHAR_BIT >= 16
sizeof(long)      * CHAR_BIT >= 32
sizeof(long long) * CHAR_BIT >= 64
CHAR_BIT         >= 8   // Number of bits in a byte

另请参见:是否保证long至少为32位?


1
嗯,这个不成立,如果sizeof(short) >= sizeof(char),我们只知道sizeof(short) >= 1(而不是>=2),这也适用于所有类型。根据此,sizeof(任何整数类型)>= 1。这是正确的,例如,我记得在Z80上sizeof(int)==1,但是long没有更强的保证吗? - Andreas Magnusson
6
C++标准的3.9.1.2规定,sizeof(long) >= sizeof(int) >= sizeof(short) >= sizeof(char),意思是long型变量的字节数不小于int型,int型不小于short型,short型不小于char型。C++标准的5.3.3.1规定,sizeof(char)、sizeof(unsigned char)、sizeof(signed char)都等于1。 - KTC
4
整形类型所能表示的最大值和最小值在 <limits.h>(因此也在 <climits>)中定义为宏。C(1990)标准的附录 E,被包含在 C++ 标准中进行引用,指定了这些宏的最小取值范围。 - KTC
4
它们分别是(2^15)-1、(2^15)-1和(2^31)-1,对应于short、int和long。如果CHAR_BIT为8(这也是其最小值),那么它们的值就是Martin York在此处回复中发布的值。 - KTC
2
@Giles:这不是我上面说的吗?sizeof(short) * CHAR_BITS >= 16,还有其他一些东西。 :-) - Martin York
显示剩余6条评论

15

在编译x64时,int和long之间的差别取决于所用编译器,其大小通常在0到4字节之间。

GCC使用LP64模型,在64位模式下,int为32位,而long为64位。

例如,MSVC使用LLP64模型,这意味着即使在64位模式下,int和long都是32位。


可能是0字节?嗯 - rogerdpack

12

C++规范本身(虽然是旧版本但足够好)并未确定这一点。

有四种带符号的整数类型: 'signed char', 'short int', 'int',和'long int'。在此列表中,每个类型提供的存储空间至少与其前面的类型相同。纯整数具有由执行环境体系结构建议的自然大小*;

[注释:也就是说,足够大以包含头文件<climits>中定义的INT_MIN和INT_MAX范围内的任何值。--- 结束注释]


7
如Kevin Haines所指出的那样,int的大小由执行环境建议的自然大小决定,该大小必须适合于INT_MIN和INT_MAX之间。
C89标准规定UINT_MAX至少应为2^16-1,USHRT_MAX为2^16-1,ULONG_MAX为2^32-1。这使得short和int至少需要16位,long需要32位。对于char,它明确规定至少应有8位(CHAR_BIT)。 C++继承了limits.h文件中的这些规则,因此在C++中,我们对这些值具有相同的基本要求。 但是,请不要推断int至少为2个字节。从理论上讲,char、int和long都可以是1个字节,如果是这样,则CHAR_BIT必须至少为32。只需记住,“字节”始终是char的大小,因此如果char更大,则字节不再仅限于8位。

我原本以为C++中不存在byte数据类型。它确实不存在,对吧?如果存在,并且byte可以有除了8位之外的其他大小,那就纯粹是愚蠢的。既然不是8位,为什么还要称其为字节呢? - Alderath

6

这取决于你的编译器。你可以保证long至少和int一样大,但不能保证它会更长。


5

C++标准如下所述:

3.9.1,§2:

共有五种带符号整数类型: "signed char"、"short int"、"int"、 "long int" 和 "long long int"。在此列表中, 每个类型提供的存储空间至少与前面的类型相同。 普通的 int 具有执行环境体系结构建议的自然大小(44); 其他带符号整数类型是为了满足特殊需要而提供的。

(44) 即,足够大,能够容纳头文件 <climits> 中 INT_MIN 和 INT_MAX 定义范围内的任何值

结论:它取决于你正在使用哪种体系结构。任何其他假设都是错误的。


5
大多数情况下,字节数和值范围由CPU的体系结构决定,而不是由C++决定。然而,C++设定了最低要求,其中litb已经解释得很好,而Martin York只犯了一些错误。
int和long不能互换使用的原因是它们的长度并不总是相同的。C语言是在PDP-11上发明的,其中一个字节有8个位,int有两个字节,并可以直接通过硬件指令处理。由于C程序员经常需要四字节算术运算,所以long被发明了,它是四个字节,由库函数处理。其他机器有不同的规格。C标准规定了一些最低要求。

5
依赖编译器供应商对基本类型大小的实现,如果您在另一台机器架构、操作系统或另一个供应商的编译器上编译代码,将会让您后悔不已。
大多数编译器供应商都提供了一个头文件,用于定义具有显式类型大小的基本类型。每当代码可能被移植到另一个编译器时(在每个情况下都是如此),应该使用这些基本类型。例如,大多数UNIX编译器有int8_t、uint8_t、int16_t、int32_t和uint32_t。Microsoft有INT8、UINT8、INT16、UINT16、INT32和UINT32。我更喜欢Borland/CodeGear的int8、uint8、int16、uint16、int32和uint32。这些名称也提醒了我们所期望值的大小/范围。
多年来,我一直使用Borland的显式基本类型名称,并#include以下C/C++头文件(primitive.h),旨在为任何C/C++编译器定义具有这些名称的显式基本类型(该头文件可能实际上并未涵盖我在Windows、UNIX和Linux上使用过的每个编译器,它也没有(但)定义64位类型)。
#ifndef primitiveH
#define primitiveH
// Header file primitive.h
// Primitive types
// For C and/or C++
// This header file is intended to define a set of primitive types
// that will always be the same number bytes on any operating operating systems
// and/or for several popular C/C++ compiler vendors.
// Currently the type definitions cover:
// Windows (16 or 32 bit)
// Linux
// UNIX (HP/US, Solaris)
// And the following compiler vendors
// Microsoft, Borland/Imprise/CodeGear, SunStudio,  HP/UX
// (maybe GNU C/C++)
// This does not currently include 64bit primitives.
#define float64 double
#define float32 float
// Some old C++ compilers didn't have bool type
// If your compiler does not have bool then add   emulate_bool
// to your command line -D option or defined macros.
#ifdef emulate_bool
#   ifdef TVISION
#     define bool int
#     define true 1
#     define false 0
#   else
#     ifdef __BCPLUSPLUS__
      //BC++ bool type not available until 5.0
#        define BI_NO_BOOL
#        include <classlib/defs.h>
#     else
#        define bool int
#        define true 1
#        define false 0
#     endif
#  endif
#endif
#ifdef __BCPLUSPLUS__
#  include <systypes.h>
#else
#  ifdef unix
#     ifdef hpux
#        include <sys/_inttypes.h>
#     endif
#     ifdef sun
#        include <sys/int_types.h>
#     endif
#     ifdef linux
#        include <idna.h>
#     endif
#     define int8 int8_t
#     define uint8 uint8_t
#     define int16 int16_t
#     define int32 int32_t
#     define uint16 uint16_t
#     define uint32 uint32_t
#  else
#     ifdef  _MSC_VER
#        include <BaseTSD.h>
#        define int8 INT8
#        define uint8 UINT8
#        define int16 INT16
#        define int32 INT32
#        define uint16 UINT16
#        define uint32 UINT32
#     else
#        ifndef OWL6
//          OWL version 6 already defines these types
#           define int8 char
#           define uint8 unsigned char
#           ifdef __WIN32_
#              define int16 short int
#              define int32 long
#              define uint16 unsigned short int
#              define uint32 unsigned long
#           else
#              define int16 int
#              define int32 long
#              define uint16 unsigned int
#              define uint32 unsigned long
#           endif
#        endif
#      endif
#  endif
#endif
typedef int8   sint8;
typedef int16  sint16;
typedef int32  sint32;
typedef uint8  nat8;
typedef uint16 nat16;
typedef uint32 nat32;
typedef const char * cASCIIz;    // constant null terminated char array
typedef char *       ASCIIz;     // null terminated char array
#endif
//primitive.h

C99规定,类似int32_t、uint64_t等的typedef必须由编译器定义,并且具有与名称所示完全相同的位数。大多数C++编译器(包括g++)允许您在C++代码中使用这些常量。 - rmeador

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