tags:

views:

1307

answers:

4

Delphi has long supported a few basic numeric types and I was wondering how they are related to each other.

In Delphi 2007 I found these declarations (some are conflicting, some are mere aliasses) :

Types.pas:

DWORD = LongWord;
Largeint = Int64;

getmem.inc:

DWORD = Integer;

Windows.pas:

DWORD = Types.DWORD;
SHORT = Smallint;
UINT = LongWord;
ULONG = Cardinal;
LONGLONG = Int64;
TLargeInteger = Int64;
ULONGLONG = UInt64;

This leads me into thinking the base signed numeric types are SmallInt, Integer and Int64. Unsigned, there's Byte, WORD and UInt64. But what is the difference between Cardinal and LongWord? (By the way, what's the original and intended casing for these types?)

And is there a type for signed 8 bit integers (Int8)?

// Int8 = ?unknown?;
UInt8 = Byte;
Int16 = SmallInt;
UInt16 = Word;
Int32 = Integer;
UInt32 = LongWord;
// Int64 already exists
// UInt64 already exists

Lastly, how should I define Int and UInt, especially with regard to C/C++ compatibility and a future switch to other platforms (possibly also 64 bit)? (A related question is, of course, how will the various numeric types be defined in 64-bit Delphi?)

+4  A: 
UInt8 = Byte
Int8 = ShortInt
UInt16 = Word
Int16 = SmallInt
UInt32 = LongWord
Int32 = LongInt
UInt64 = UInt64
Int64 = Int64

int = Integer
uint = Cardinal

NativeInt (generic, depends on CPU register size)
NativeUInt (generic, depends on CPU register size)

Cardinal and Integer are generic types. For 16 bit they were 16 byte large and for 32 bit they are 32 bit large. For 64 bit the Windows 64bit platform (LLP64) defines them as 32 bit. The new NativeInt and NativeUInt types are now the CPU register sized types.

Andreas Hausladen
Thanks for mentioning LLP64, which led me to this article : http://en.wikipedia.org/wiki/64-bit#Specific_data_modelsAmazing how much stuff one can forget... ;-)
PatrickvL
FPC defines 64-bit unsigned as QWORD.
Marco van de Voort
+5  A: 

The signed one-byte integer type is ShortInt. You can remember its size by the fact that it's not the same size as usual C implementations of the short type.

As for capitalization, capitalize the first letter. The documentation tends to leave the "int" part at the end lowercase, as in Longint, but I think it's more common to capitalize it. Don't write the types in all capitals unless you're using Platform SDK types and you want your code to show its C roots; otherwise I'd just write Word and DWord, Long and ULong, etc.)

Delphi 2009, perhaps earlier, already defines types like Int8 and UInt32. As for how to define Int and UInt, I'd say don't. The language you're using already defines Integer and Cardinal; don't introduce new type names when you don't have to. Keep the names you already have, and then everyone else will know what you're talking about. (Besides, Int is already a function in the System unit.)

Use Cardinal when you want an unsigned type and don't care about its size; use LongWord when the variable must be exactly four bytes. Likewise for Integer and LongInt. Use Cardinal when you want a four-byte unsigned type; use LongWord when you want a generic unsigned type and don't care about the size. Likewise for Integer and LongInt, nowadays. If you're writing 16-bit code, use LongInt when you need four bytes and use Integer when you don't care about the size; Cardinal and LongWord didn't exist in Delphi's and Turbo Pascal's 16-bit days.

The common wisdom for years had been that Integer and Cardinal would become 64-bit types on a 64-bit compiler, but that is apparently not the case. Instead, they will remain 32-bit types, just as their counterparts in Microsoft C++ do. Furthermore, there will be a new type, NativeInt, which will be a 64-bit type in a 64-bit compiler. The LongInt and LongWord types will become 64-bit types because they have always been the same size as the Pointer type, which was 32 bits even in 16-bit times.

Rob Kennedy
"The LongInt and LongWord types will become 64-bit types". That's something that was discussed and no consensus was found, especially because they were advertised as the non-generic 32 bit types since the TurboPASCAL days. And Pointers in the 16 bit land where 20 bit large not 32 bit: "(Seg16 << 4) + Ofs16)"
Andreas Hausladen
Pointers were 32 bits in the sense that SizeOf(Pointer) = 4. It has never been the case that SizeOf(Pointer) = 2.5.
Rob Kennedy
... and integer was 16-bit in TP.
Marco van de Voort
I doubt longint (and longword) will be 64-bit. Most OSes nowadays are LP64 or LLP64, not ILP64. Though some more rare ones (AIX iirc) are.
Marco van de Voort
Hey, I'm just going off of what CodeGear employee Allen Bauer wrote in the newsgroup thread I linked to. Andreas apparently also works for CodeGear, so he knows better than I what's really going on (which evidently is nothing, yet). If LongInt were 64 bits and Integer remained at 32, then that would be LP64. I now understand that ILP64 isn't very popular, but I think for several years most people naturally expected Delphi's Integer to grow to 64 bits just like it had grown to 32 bits before. (Wikipedia says AIX is LP64.)
Rob Kennedy
+1  A: 

Cardinal and Integer are aliases.

Cardinal ==> LongWord  (unsigned)
Integer  ==> LongInt   (signed)

Ian Boyd
Wrong! LongWord = cardinal = DWORD = **unsigned** 32-bit integer,
Andreas Rejbrand
Whoops, had the intermediate names reversed (fixed). The outer idea is correct `Integer` is an alias for an `Int32`, `Cardinal` is an alias for a `UInt32` (to use the clearer .NET terminology)
Ian Boyd
+1  A: 

To get "the original and intended casing" press Ctrl-Space, Return after you typed a type name (i.e. use code completion).

Ulrich Gerhardt