Delphi and the Integer data types

There’s a lot of discussions on CodeGear newsgroups lately regarding the Integer data types and 64 bit support. Just wanted to clarify some points for people waiting for the 64 bit release of RAD Studio (due somewhere in 2010).

The “fundamental” Integer types (the ones that have constant sizes on all platforms) are:

  • Byte (1 Byte, Unsigned)
  • UInt8 (alias for Byte)
  • ShortInt (1 Byte, Signed)
  • Int8 (alias for ShortInt)
  • Word (2 Bytes, Unsigned)
  • UInt16 (alias for Word)
  • SmallInt (2 Bytes, Signed)
  • Int16 (alias for SmallInt)
  • LongWord (4 Bytes, Unsigned)
  • UInt32 (alias for LongWord)
  • LongInt (4 Bytes, Signed)
  • Int32 (alias for LongInt)
  • UInt64 (8 Bytes, Unsigned)
  • Int64 (8 Bytes, Signed)

Previously listed Integer types are fixed in size — meaning that no matter what OS/CPU you’re running on, these types will have the same size.

CPU specific Integer types are listed below:

  • NativeUInt (Unsigned, depends on CPU register size)
  • NativeInt (Signed, depends on CPU register size)

Note that the sizes of this Integer types actually depend on the “target architecture” you’re going to compile you program for. So if you are targeting Windows for 64 bit you will get 8 Byte wide native Integers. If you target the 32 bit Windows and you’re running your application on 64 bit Windows, NativeInt will still be 4 bytes wide.

And at last, the “generic” data types:

  • Cardinal (Unsigned, depends on OS definition of Integer)
  • Integer (Signed, depends on OS definition of Integer)

Yes, it might be confusing, but Integer and Cardinal are not CPU specific, but rather OS specific. In the case of Windows for 64 bit, the “int” is still 4 Bytes wide.

So what happens if you want to transition your Delphi application to 64 bit Windows? Not much really. Few things will actually break, the most usual culprits will be:

  • Windows API calls. Most Windows APIs that require handles can break down for you if you for  instance consider a HWND to be a Cardinal. HWND will be 64 bit while Cardinal will stay 32 bit wide. The same applies to a lot of other Windows functions.
  • Casting a Pointer to an Integer and back. Pointer is actually the same size as the NativeInt type so be sure to fix these issues in your code. Just replace Integer with NativeInt. Many developers cast a Pointer to an Integer to perform some arithmetic so that would be a pretty common case. I hope the compiler guys will add a warning if you cast between Integer and Pointer data types.
  • The Tag property. I know a lot of people rely on the Tag property of VCL components to keep some state information in the GUI objects. Because the Tag property is currently defined as an Integer and you need to store an Object there, casting is performed — which brings us to the second point. But no need to worry here as the Tag property will become a NativeInt so nothing will break.