Delphi SizeOf(NativeInt)与x86-64上的C sizeof(int)。为什么尺寸差异?

时间:2013-09-12 18:01:32

标签: c delphi x86-64 pascal sizeof

前言

因此经过很长一段时间的C工作后,我回到Delphi,发现Delphi中有一些新东西。一个是 NativeInt

令我惊讶的是,我发现Delphi和C处理x86-64不同的“原生整数” 1 类型。 Delphi NativeInt 似乎表现得像 C void * Delphi Pointer ,这与我对名称的期望相反。

Delphi中,NativeInt 的大小为64位。在代码中表示:

SizeOf(NativeInt) = SizeOf(Pointer) = SizeOf(Int64) = 8

C只有64位指针。 int 仍为32位。在代码 2 中表达:

sizeof(int) == 4 != sizeof(void *) == 8

即使Free Pascal编译器 3 也同意 NativeInt 的大小。

问题

为什么 Delphi NativeInt 选择64位, C int 选择32位?

当然,根据语言文档/规范,两者都是有效的。但是,“语言允许它”并不是一个真正有用的答案。

我想这与执行速度有关,因为这是今天C的主要卖点。维基百科和其他消息来源都说x86-64确实有64位操作数寄存器。但是,它们还声明默认操作数大小为32位。因此,与32位操作数相比,64位操作数的操作可能更慢?或者64位寄存器可以同时执行2个32位操作?这是一个原因吗?

编译器的创建者是否确实选择了这些尺寸?

脚注

  1. 我正在将 Delphi NativeInt C int 进行比较,因为名称/规范表明它们具有相似的用途。我知道还有 Delphi Integer ,其行为类似于x68上的 C int 和Delphi中的x86-64。
  2. sizeof()在C中返回 char 的倍数。但是, char 在x86-64上是1个字节。
  3. 在Delphi模式和 NativeInt 的默认模式下执行此操作。默认模式下的其他整数类型是另一种蠕虫病毒。

2 个答案:

答案 0 :(得分:10)

NativeInt只是一个与指针大小相同的整数。因此,它改变了不同平台上的大小。 documentation完全是这样说的:

  

NativeInt的大小等于当前平台上指针的大小。

NativeInt的主要用途是存储操作系统句柄之类的东西,后台实际上是内存地址。您不应该使用它来执行算术运算,存储数组长度等。如果您尝试这样做,那么在程序的32位和64位版本之间共享代码会变得更加困难。

你可以认为Delphi NativeInt直接等同于.net类型IntPtr。在C和C ++中,OS句柄类型通常被声明为void*,它是指针类型而不是整数类型。但是,如果您愿意,最好使用类似intptr_t的类型。

您使用术语“本机整数”来描述NativeInt,但是尽管名称很重要,但要认识到NativeInt不是该语言的本机整数类型。那将是IntegerNativeInt中的本机是指底层硬件平台而不是语言。

Delphi类型Integer,语言本机整数,与C类型int匹配,相应的语言本机类型。在Windows上,32位和64位系统的这些类型都是32位宽。

当Windows设计人员开始使用64位Windows时,他们对int在从16位到32位系统的转换中从16位更改为32位时所发生的事情有了敏锐的记忆。这根本不好玩,虽然这显然是正确的决定。这一次,从32到64,没有令人信服的理由使int成为64位类型。如果Windows设计师这样做了,那么移植工作就会变得更加困难。因此他们选择将int作为32位类型。

在性能方面,AMD64架构旨在在32位类型上高效运行。由于32位整数的大小是64位整数的一半,因此通过在64位系统上仅使int为32位来减少内存使用量。这将带来性能优势。

几条评论:

  • 您声明“C只有64位指针”。事实并非如此。 32位C编译器通常使用具有32位指针的平坦32位存储器模型。
  • 你也说,“在Delphi中NativeInt的大小是64位”。事实并非如此。根据目标,它可以是32位或64位宽。

答案 1 :(得分:0)

请注意,NativeInt 意味着与指针交互!

问题是nativeInt已签名 通常这是你想要的,因为指针指向数据块的开头。 否定抵消会在此处为您提供访问权限违规。
如果你有一个指向中间的指针(因为你正在做索引或类似的东西),那么应用负偏移量并且NativeInt又名IntPtr进入视野。

对于标准指针(指向开始):使用UIntPtr,因为当偏移量大于2 ^ 31/2 ^ 63时,它将细分。
(可能在32位平台上,而不是在64位平台上)

出于这个原因,有一个UIntPtr,它完全映射到C等价物 UIntPtrNativeUint

用例
您选择使用哪种类型取决于用例。

答:我想要最快的整数 - >选择Int32 aka integer;
B1:我想要一个整数来做指针运算 - >选择UIntPtr又名NativeUInt *。
B2:我用我的指针进行索引 - >选择IntPtr又名NativeInt C:我想要一个大整数,但不希望Int64在X86上给我的大幅减速 - >选择NativeInt。 D:我想要一个bigint:选择Int64。 (但是知道它在X86上会很慢)。

*)如果你想向你的代码的读者清楚说明你弄乱了指针,你需要明确命名它UIntPtr