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?
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.
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.
Difference between long int and long long int in C/C++ S. No. Data Type Memory (bytes) Range 1 int 4 -2^15 to 2^15 – 1 2 Long int 4 -2^31 to 2^31 – 1 3 Long long int 8 -2^63 to 2^63 – 1
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.
| 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 |
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"
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.
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.
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
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?
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.
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.
Integer
is the underlying platform's C++ int
. LongInt
is the underlying platform's C++ long int
. Cardinal
is the underlying platform's C++ unsigned int
. 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.
I suggest you check Delphi documentation for best explanation: http://docwiki.embarcadero.com/RADStudio/XE5/en/Delphi_Data_Types
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With