10
votes

In Delphi, what is the difference between LongInt and Integer, LongWord and Cardinal ?

and sometimes I find the usage of DWORD, what is it?

Are they consistent in all versions of Delphi? which one should I stick to?

6
I believe, asking online documentation for DWORD will give you an explanation right away.Free Consulting

6 Answers

9
votes

In short: Longint and Longword are fixed size integers, the former signed, the latter unsigned, and both usually 32 bits in size. Their size is platform-dependent in XE8, but fixed size (32 bits) in XE7 and earlier versions.

Integer and Cardinal are not fixed size. They are so called "generic" integers (do not confuse this with generics, which is a different pair of shoes), i.e. they should preferrably be used when an integral type is required, regardless of the size. Depending on version and platform, the size of Integer and Cardinal may differ. Currently, they are the same size and type as Longint and Longword.

The sizes of the fixed size types don't differ between versions or platforms. You should use these types where you must interface with code or data from other sources than your own program, in other words, where exact binary compatibility is important, e.g. when calling API functions. Hence the use of types like DWORD, etc.

Note that current versions have aliases for types like Byte or Smallint. They are Int8, UInt8, Int16, UInt16, etc... up to UInt64. ISTM that these names are easier to remember than e.g. "Smallint" (16 bit signed) or "Shortint" (8 bit signed).

So use Integer and Cardinal whenever that is possible, since these are probably the ideal types for the platform and version. Use the fixed size types like Byte, Smallint, Longint or UInt64, just to name a few, when exact binary compatiblity with other data is required.

Update

Since there has been some confusion (see link near the top), and since nowadays not Longint and Longword are considered fixed size platform independent anymore, but, weirdly enough, Integer and Cardinal are considered fixed size, I more and more tend to use the (U)IntXX versions like UInt16 or Int32. One exception is my use of Byte, which I can't imagine ever changing its size (of 1).

And of course I will use Integer and Cardinal for anything that needs an integral type for which the size is not so important, e.g. for loop counters, etc.

3
votes
  • Delphi Integer is the underlying platform's C++ int.
  • Delphi LongInt is the underlying platform's C++ long int.
  • Delphi Cardinal is the underlying platform's C++ unsigned int.
  • Delphi LongWord is the underlying platform's C++ unsigned long int.

All four of these types are platform dependent.

On all supported platforms at the time of writing, Integer and Cardinal are 32 bit types. The types are platform dependent, it so happens that on all supported platforms the types are the same size.

On 64 bit *nix platforms, LongInt and LongWord are 64 bit types. On all other supported platforms, at the time of writing, the types are 32 bit types.

The key point is that these types are all platform dependent.

DWORD is a type alias used by the Windows API. Use it only when using that API.

Should you use Integer or LongInt? That depends on your use. As a rule, for interop use whichever type matches the C++ code. Otherwise, for most uses Integer is appropriate. Of course, this is a generic answer to your general question.

1
votes

I suggest you check Delphi documentation for best explanation: http://docwiki.embarcadero.com/RADStudio/XE5/en/Delphi_Data_Types

0
votes

Short Version

| Type        | 16-bit platform | 32-bit platform | 64-bit platform  |
|-------------|-----------------|---------------- |------------------|
| Integer     | 16-bit signed   |            32-bit signed           | "generic type"
| Cardinal    | 16-bit unsigned |            32-bit unsigned         | "generic type"

| Longint     | 32-bit signed   | 32-bit signed   | 64-bit signed    | "fundamental type"
| Longword    | n/a             | 32-bit unsigned | 64-bit unsigned  | "fundamental type"
| Int64       | n/a             | 64-bit signed   | 64-bit signed    | "fundamental type"
| UInt64      | n/a             | 64-bit unsigned | 64-bit unsigned  | "fundamental type"
| Int32       | n/a             |            32-bit signed           |  
| UInt32      | n/a             |            32-bit unsigned         | 

| NativeInt   | n/a             | 32-bit signed   | 64-bit signed    |
| NativeUInt  | n/a             | 32-bit unsigned | 64-bit unsigned  |

| FixedInt    | n/a             |            32-bit signed           |
| FixedUInt   | n/a             |            32-bit unsigned         |

Long answer

We all know what they should have done:

| Type        | 16-bit platform | 32-bit platform | 64-bit platform  |
|-------------|-----------------|---------------- |------------------|
| Integer     | 16-bit signed   | 32-bit signed   | 64-bit signed    | "generic type"
| Cardinal    | 16-bit unsigned | 32-bit unsigned | 64-bit unsigned  | "generic type"

| SmallInt    |                   16-bit signed                      | "fundamental type"
| Word        |                   16-bit unsigned                    | "fundamental type"
| Longint     |                   32-bit signed                      | "fundamental type"
| Longword    |                   32-bit unsigned                    | "fundamental type"
| Int64       |                   64-bit signed                      | "fundamental type"
| UInt64      |                   64-bit unsigned                    | "fundamental type"
  • fundamental types don't change
  • generic types (aliases) do

But that's not what they did. So we are where we are.

Presumably Int32 will always be a signed 32-bit integer; but guarantees have been broken before.

Bonus Reading

Bonus Chatter

From the Delphi 5 help:

Integer types


An integer type represents a subset of the whole numbers. The generic integer types are Integer and Cardinal; use these whenever possible, since they result in the best performance for the underlying CPU and operating system. The table below gives their ranges and storage formats for the current 32-bit Object Pascal compiler.

Type      Range                    Format
--------  -----------------------  ---------------
Integer   –2147483648..2147483647  signed 32-bit
Cardinal  0..4294967295            unsigned 32-bit

Fundamental integer types include Shortint, Smallint, Longint, Int64, Byte, Word, and Longword.

Type      Range                    Format
--------  -----------------------  ----------------
Shortint  –128..127                signed 8-bit
Smallint  –32768..32767            signed 16-bit
Longint   –2147483648..2147483647  signed 32-bit
Int64     –2^63..2^63–1            signed 64-bit
Byte      0..255                   unsigned 8-bit
Word      0..65535                 unsigned 16-bit
Longword  0..4294967295            unsigned 32-bit

In general, arithmetic operations on integers return a value of type Integer—which, in its current implementation, is equivalent to the 32-bit Longint. Operations return a value of type Int64 only when performed on an Int64 operand.

Notice the "in its current implementation, is equivalent to Longint". The idea back then was that Integer would change; little did they realize that it was Longint that would change.

From the Delphi 1 User's Guide:

Data Types


Object Pascal has several data types built into the language. You can create variables of any of these predefined types. The following table lists the predefined data types:

Table 5.1 Object Pascal predefined data types

  • Integer: Numbers without a fractional part, within the range of –32768 to 32767. Requires two bytes of memory.
  • Shortint: Numbers without a fractional part, within the range of –128 to 127. Requires only one byte of memory.
  • Longint: Numbers without a fractional part, within the range of –2147483647 to 2147483647. Requires four bytes of memory.
  • Byte: Numbers without a fractional part, within the range of 0 to 255. Requires one byte of memory.
  • Word: Numbers without a fractional part, within the range of 0 to 65535. Requires two bytes of memory

From the Delphi XE6 Help:

Integer Types ================

An integer type represents a subset of the integral numbers.

Integer types can be platform-dependent and platform-independent.

Platform-Dependent Integer Types


The platform-dependent integer types are transformed to fit the bit size of the current compiler platform. The platform-dependent integer types are NativeInt and NativeUInt. Using these types whenever possible, since they result in the best performance for the underlying CPU and operating system, is desirable. The following table illustrates their ranges and storage formats for the Delphi compiler.

Platform-dependent integer types

Type         Range                    Format                                  Alias  
-----------  -----------------------  --------------------------------------  ------------
NativeInt    -2147483648..2147483647  Signed 32-bit on 32-bit platforms or    Integer
             -2^63..2^63-1            Signed 64-bit on 64-bit platforms       Int64 
NativeUInt   0..4294967295            Unsigned 32-bit on 32-bit platforms or  Cardinal
             0..2^64-1                Unsigned 64-bit on 64-bit platforms     UInt64

Platform-Independent Integer Types

Platform-independent integer types always have the same size, regardless of what platform you use. Platform-independent integer types include ShortInt, SmallInt, LongInt, Integer, Int64, Byte, Word, LongWord, Cardinal, and UInt64.

Platform-independent integer types

Type         Range                    Format           Alias  
-----------  -----------------------  ---------------  ------
ShortInt     -128..127                Signed 8-bit     Int8 
SmallInt     -32768..32767            Signed 16-bit    Int16 
LongInt      -2147483648..2147483647  Signed 32-bit    Int32 
Integer      -2147483648..2147483647  Signed 32-bit    Int32 
Int64        -2^63..2^63-1            Signed 64-bit    
Byte         0..255                   Unsigned 8-bit   UInt8 
Word         0..65535                 Unsigned 16-bit  UInt16 
LongWord     0..4294967295            Unsigned 32-bit  UInt32 
Cardinal     0..4294967295            Unsigned 32-bit  UInt32 
UInt64       0..2^64-1                Unsigned 64-bit 

Notice how Integer and Cardinal were documented as platform dependent? Also notice how LongInt and LongWord were documented as platform independent?

-1
votes

Integer is a 32-bit signed integer type - Longint is an alias for this type. Cardinal is a 32-bit unsigned integer type - LongWord and DWORD are aliases for this type.

-1
votes

Previously there were fundamental integer types (should never change) and generic types, which theoretically could be different for different platforms, although integer types never actually changed. Now, in the documentation for XE6, there is a more logical, simple and clear definition of integer types, and only two platform-dependent integer types:

NativeInt
NativeUInt

All other integer types are platform-independent:

ShortInt 
SmallInt 
LongInt 
Integer 
Int64 
Byte 
Word 
LongWord 
Cardinal 
UInt64 

For details, I suggest reading the "Simple Types" section of Help.