在 64 位 Windows 上 long 的位大小是多少?

Posted

技术标签:

【中文标题】在 64 位 Windows 上 long 的位大小是多少?【英文标题】:What is the bit size of long on 64-bit Windows? 【发布时间】:2010-09-27 22:09:28 【问题描述】:

不久前,有人告诉我long 在 64 位机器上不是 64 位,我应该始终使用 int。这对我来说没有意义。我看过文档(例如 Apple 官方网站上的文档)说 long 在为 64 位 CPU 编译时确实是 64 位。我在 64 位 Windows 上查找了它,发现

Windows:longint 保持 32 位长度,以及特殊的新数据类型 为 64 位整数定义。

(来自http://www.intel.com/cd/ids/developer/asmo-na/eng/197664.htm?page=2)

我应该使用什么?如果不在 Windows 上,我是否应该将 uwsw ((un)signed width) 定义为 long,否则检查目标 CPU 位大小?

【问题讨论】:

在带有 MSVC++ int 和 long 的 Windows 上是 32 位:msdn.microsoft.com/en-us/library/3b2e7499.aspx。但是,允许例如用于存储超过 4G 项的向量,size_t 为 64 位。因此,需要使用 int64_t 而不是 int 进行迭代,例如可能包含超过 4G 项的向量。 Cygwin sizeof(long) == 8, even on Windows :-) @LưuVĩnhPhúc,size_t 在负数附近变得棘手,因为size_t 是无符号的。所以 for(size_t i=0; i<v.size()-2; i++) 对向量大小 0 和 1 失败。另一个例子:for(size_t i=v.size()-1; i>=0; i--) 如果您正在对指针进行数学运算(即使用size_t 值,那么结果应保存在ptrdiff_t 类型的变量中 - 该变量设计得足够大以容纳这样的结果并且正是出于这个原因,它是一个 signed 类型!) @OrionEdwards 实际上是关于目标平台 ABI。 Cygwin 拥有自己的类似 POSIX 的 ABI,并选择了对 POSIX 更友好的 LLP64 模型,而 Mingw 坚持使用其 LP64 模型的 Win32 ABI。出于这个原因,在与 Mingw 捆绑在一起的 GCC 中 long 是 32 位,而在 Cygwin 中的 GCC 中是 64 位。 【参考方案1】:

在 Unix 世界中,对于 64 位平台,整数和指针的大小有几种可能的安排。最广泛使用的两个是 ILP64(实际上,只有极少数的例子;Cray 就是这样一个例子)和 LP64(几乎所有其他的例子)。缩写词来自“int, long, pointers are 64-bit”和“long, pointers are 64-bit”。

Type           ILP64   LP64   LLP64
char              8      8       8
short            16     16      16
int              64     32      32
long             64     64      32
long long        64     64      64
pointer          64     64      64

ILP64 系统被 LP64 取代(也就是说,根据 Aspen 小组的建议,几乎所有后来的进入者都使用 LP64;只有具有 64 位操作传统的系统才使用不同的方案) .所有现代 64 位 Unix 系统都使用 LP64。 MacOS X 和 Linux 都是现代 64 位系统。

Microsoft 使用不同的方案转换到 64 位:LLP64('long long,指针是 64 位')。这意味着 32 位软件可以在不改变的情况下重新编译。它的缺点是与其他人所做的不同,并且还需要修改代码以利用 64 位容量。总是需要修改;它只是一组与 Unix 平台所需的不同的修订。

如果您围绕平台中立的整数类型名称设计软件,可能使用 C99 <inttypes.h> 标头,当类型在平台上可用时,提供有符号(列出)和无符号(未列出;前缀)用'你'):

int8_t - 8 位整数 int16_t - 16 位整数 int32_t - 32 位整数 int64_t - 64 位整数 uintptr_t - 大到足以容纳指针的无符号整数 intmax_t - 平台上最大的整数大小(可能大于int64_t

然后,您可以在重要的地方使用这些类型对您的应用程序进行编码,并对系统类型(可能不同)非常小心。有一个intptr_t 类型——用于保存指针的有符号整数类型;您应该计划不使用它,或者仅将其用作两个 uintptr_t 值相减的结果 (ptrdiff_t)。

但是,正如问题所指出的那样(难以置信),64 位机器上整数数据类型的大小有不同的系统。习惯它;世界不会改变。

【讨论】:

对于那些使用时间足够长的用户来说,64 位转换与 80 年代中期从 16 位到 32 位的转换有一些相似之处。有一些计算机是 IL32 和其他是 L32(将新符号适应旧问题)。有时“int”是 16 位,有时是 32 位。 不要忘记这仅适用于 C-ish 语言。其他人有更理智的规范,其中 a) 编译器编写者不允许随意选择数据类型的大小或 b) 数据类型的物理表示不会“泄漏”或 c) 整数总是无限大。 True - 但是对于那些指定行为的语言,首先没有问题。例如,Java 有一个“长”,但大小是固定的(64 位?),在所有平台上。因此,移植到 64 位机器没有问题;大小不变。 @TomFobear:ILP64 提出了一个主要问题——您将 32 位类型称为什么?或者,如果你把 32 位类型称为short,那你怎么称呼 16 位类型呢?如果您将 16 位类型 char 称为 UTF-16 等,那么您如何称呼 8 位类型?因此,使用 LP64 会为您留下 8 位 char、16 位 short、32 位 int、64 位 long,当(如果?) 这变得相关。在那之后,你得到的 256 的幂比你在 C 中的名字还要多(好吧,我想你可以有一个 256 位的intmax_t,然后你才会用完)。 LP64 有优点。 也许这对你们来说是显而易见的,但我认为值得注意的是,C# 使用的整数大小与其他所有内容不同。由于 C# 使用 64 位 long (msdn.microsoft.com/en-us/library/ms173105.aspx),我最近在与 DLL 接口时遇到了麻烦。【参考方案2】:

不清楚问题是关于 Microsoft C++ 编译器还是 Windows API。但是,没有 [c++] 标签,所以我认为它是关于 Windows API 的。一些答案因链接失效而受到影响,因此我提供了另一个可能失效的链接。


有关INTLONG 等 Windows API 类型的信息,MSDN 上有一个页面:

Windows Data Types

这些信息也可以在各种 Windows 头文件中找到,例如 WinDef.h。我在这里列出了一些相关的类型:

类型 |南美 | x86 | x64 ----------------------------+------+--------+------ - 字节,布尔值 |你 | 8 位 | 8位 ----------------------------+------+--------+------ - 简短 |小号 | 16 位 | 16 位 USHORT,字 |你 | 16 位 | 16 位 ----------------------------+------+--------+------ - INT,长 |小号 | 32 位 | 32 位 UINT, ULONG, DWORD |你 | 32 位 | 32 位 ----------------------------+------+--------+------ - INT_PTR、LONG_PTR、LPARAM |小号 | 32 位 | 64 位 UINT_PTR、ULONG_PTR、WPARAM |你 | 32 位 | 64 位 ----------------------------+------+--------+------ - 龙龙 |小号 | 64 位 | 64 位 乌龙龙,QWORD |你 | 64 位 | 64 位

“S/U”列表示有符号/无符号。

【讨论】:

【参考方案3】:

MSDN 上的这篇文章引用了一些类型别名(在 Windows 上可用),它们的宽度更加明确:

http://msdn.microsoft.com/en-us/library/aa505945.aspx

例如,虽然您可以使用 ULONGLONG 来引用 64 位无符号整数值,但您也可以使用 UINT64。 (对于 ULONG 和 UINT32 也是如此。)也许这些会更清楚一点?

【讨论】:

是否可以保证 uint32_t 和 DWORD 可以互换?不难想象他们可能不是[例如。如果前者是 32 位 int 而后者是 32 位 long,则 gcc 将假定指向一种类型的指针将无法为另一种类型命名,尽管它们的表示形式匹配]。【参考方案4】:

Microsoft 还为与指针大小相同的整数定义了 UINT_PTR 和 INT_PTR。

这是list of Microsoft specific types - 这是他们的驱动程序参考的一部分,但我相信它也适用于一般编程。

【讨论】:

【参考方案5】:

为您的编译器/平台了解它的最简单方法:

#include <iostream>

int main() 
  std::cout << sizeof(long)*8 << std::endl;

乘以 8 是从字节中获取位。

当您需要特定大小时,使用其中一种预定义类型的库通常是最容易的。如果不希望这样做,您可以执行 autoconf 软件经常发生的事情,并让配置系统确定所需大小的正确类型。

【讨论】:

没关系,但 8 位字节实际上并不是 C 规范的一部分(C 标准的第 3.6 和 5.2.4.2.1 条)。尽管您很难找到一台不是 8 位的机器,但您可以检查 LONG_BIT 以了解您的 long 数据类型有多大。 当然,你是对的,它实际上是依赖于架构的(“数据存储的可寻址单元大到足以容纳执行环境的基本字符集的任何成员”),但最常用的相当于 8 位的架构。 但是 OP 没有询问 他的 编译器/平台;他专门询问了 64 位 Windows — 大概是因为他没有方便地访问 64 位 Windows 系统进行测试。 准确地说,你必须使用sizeof(long)*CHAR_BIT,因为一个字节中并不总是有8位【参考方案6】:

long 在 Windows 平台上的大小为 32 位(4 字节)。

您可以使用sizeof(long) 进行检查。

【讨论】:

【参考方案7】:

如果您需要使用特定长度的整数,您可能应该使用一些独立于平台的标头来帮助您。 Boost 是一个值得关注的好地方。

【讨论】:

以上是关于在 64 位 Windows 上 long 的位大小是多少?的主要内容,如果未能解决你的问题,请参考以下文章

64 位 dll 的大小比 32 位大 50%

检测 32 位或 64 位 Windows

关于Java数据类型的位

为啥在 x64 Java 中 long 比 int 慢?

32位和64位的区别的位是啥意思

C语言的位运算