Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-03

History of the Cardinal data type?

26 messages · 9 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

Just curious. What is the history behind the Cardinal data type. As per the FPC documentation, it is always mapped to the LongWord type. I presume it is the same in Delphi.

So why does the Object Pascal language have a Cardinal type? Why couldn't LongWord be used instead?

Regards,
- Graeme -

Marco van de Voort
to Graeme Geldenhuys

In our previous episode, Graeme Geldenhuys said:

Just curious. What is the history behind the Cardinal data type. As per the FPC documentation, it is always mapped to the LongWord type. I presume it is the same in Delphi.

Cardinal is the Wirthian designation for the default unsigned integer, just like "integer" is for signed.

The Delphi side of things is more convoluted because pre-int64 Delphis had 31-bits Cardinals.

So why does the Object Pascal language have a Cardinal type? Why couldn't LongWord be used instead?

See above. Variable size type vs fixed size type.

Dmitry Boyarintsev
to Graeme Geldenhuys: Just curious. What is the history behind the Cardinal data type. As per the FPC…

On Tue, Mar 29, 2016 at 11:06 AM, Graeme Geldenhuys <

Show quoted text 5 lines
wrote: So why does the Object Pascal language have a Cardinal type? Why couldn't LongWord be used instead?

In Delphi world LongWord is 64-bit on 64-bit iOS platform and it is 32-bit on 64-bit Windows platform.

http://docwiki.embarcadero.com/RADStudio/XE8/en/What's_New#Changes_in_LongInt_and_LongWord_Size_for_64-bit_iOS_Platforms

Who know what it would be for future Linux 64 target?! Thus using LongWord as 32-bit for Delphi is quite volatile.

Cardinal is instead always 32-bit
http://docwiki.embarcadero.com/Libraries/XE8/en/System.Cardinal

thanks,
Dmitry

Michael Van Canneyt
to Dmitry Boyarintsev: On Tue, Mar 29, 2016 at 11:06 AM, Graeme Geldenhuys < In Delphi world LongWord is 64-bit…
Dmitry Boyarintsev wrote 8 lines
On Tue, Mar 29, 2016 at 11:06 AM, Graeme Geldenhuys < > wrote: > So why does the Object Pascal language have a Cardinal type? Why > couldn't LongWord be used instead? > In Delphi world LongWord is 64-bit on 64-bit iOS platform and it is 32-bit on 64-bit Windows platform.

Which is quite confusing and a really bad decision. Basic integer types should not depend on the OS. On the CPU, yes.

Michael.

Graeme Geldenhuys
to Dmitry Boyarintsev: On Tue, Mar 29, 2016 at 11:06 AM, Graeme Geldenhuys < In Delphi world LongWord is 64-bit…
Dmitry Boyarintsev wrote 5 lines
In Delphi world LongWord is 64-bit on 64-bit iOS platform and it is 32-bit on 64-bit Windows platform. http://docwiki.embarcadero.com/RADStudio/XE8/en/What's_New#Changes_in_LongInt_and_LongWord_Size_for_64-bit_iOS_Platforms

Wow, that sounds like a terrible idea. I fully agree with Michael's statement - data type sizes should not be based on OS, but on CPU.

Regards,
- Graeme -

Dmitry Boyarintsev
to Michael Van Canneyt: Which is quite confusing and a really bad decision. Basic integer types should not depend…

On Tue, Mar 29, 2016 at 11:20 AM, Michael Van Canneyt <

Show quoted text 7 lines
wrote: Which is quite confusing and a really bad decision. Basic integer types should not depend on the OS. On the CPU, yes. I guess they tried to make iOS platform a selling point and be more

C-like.
Just to remember that Strings are zero-based there, by default.

I believe this came with anticipation that the platform will not use (much) of existing code base.

thanks,
Dmitry

Graeme Geldenhuys
to Marco van de Voort: In our previous episode, Graeme Geldenhuys said: Cardinal is the Wirthian designation for…
Marco van de Voort wrote
Cardinal is the Wirthian designation for the default unsigned integer, just like "integer" is for signed.

Thanks Marco, that fulfils my curiosity. :)

On a side note:
The reason I asked this question. I'm working on code with many Record types with fields of type Word, Smallint etc, than then some Cardinal fields got mixed in too. I would normally use LongWord instead of Cardinal to keep to a consistent naming convention. But from your comments Cardinal has a long history in Pascal.

Regards,
- Graeme -

Dmitry Boyarintsev
to Graeme Geldenhuys

On Tue, Mar 29, 2016 at 11:31 AM, Graeme Geldenhuys <

Show quoted text 12 lines
wrote: On 2016-03-29 16:17, Dmitry Boyarintsev wrote: > In Delphi world LongWord is 64-bit on 64-bit iOS platform and it is 32-bit > on 64-bit Windows platform. So what happened when they introduced Android support? Yet another definition or copied one of the others? From what I can see they currently support 32-bit processors for Android

devices.
(
http://docwiki.embarcadero.com/RADStudio/Seattle/en/Android_Devices_Supported_for_Application_Development )
So Cardinal is still 32-bit there. I'd think it will grow to 64-bit as soon as arm64 is supported.

thanks,
Dmitry

Sven Barth
to Graeme Geldenhuys: Thanks Marco, that fulfils my curiosity. :) On a side note: The reason I asked this…

Am 29.03.2016 17:27 schrieb "Graeme Geldenhuys" <

Show quoted text 15 lines
: On 2016-03-29 16:13, Marco van de Voort wrote: > Cardinal is the Wirthian designation for the default unsigned integer, > just like "integer" is for signed. Thanks Marco, that fulfils my curiosity. :) On a side note: The reason I asked this question. I'm working on code with many Record types with fields of type Word, Smallint etc, than then some Cardinal fields got mixed in too. I would normally use LongWord instead of Cardinal to keep to a consistent naming convention. But from your comments Cardinal has a long history in Pascal.

I usually use LongWord, too, but with the recent discovery that in Delphi LongWord is not always 32-bit (and my tendency to confuse Short and SmallInt) I'm inclined to use the (U)IntX (with X being a element of [8, 16, 32, 64]) types to avoid any confusion and surprises.

Regards,
Sven

Graeme Geldenhuys
to Sven Barth
Sven Barth wrote
I usually use LongWord, too,

My preference is based on the fact that they often translate nicely from C code examples and APIs. Plus I know those types and sizes pretty well (at least when in comes to Free Pascal).

but with the recent discovery that in Delphi

Luckily Delphi is of no concern to me. :)

I'm inclined to use the (U)IntX (with X being a element of [8, 16, 32, 64]) types to avoid any confusion and surprises.

That's not a bad idea either... I'll look into that for future code.

Regards,
- Graeme -

Graeme Geldenhuys
to Michael Van Canneyt: It used to be opposite, if I recall correctly. Longword used to be Cardinal. I guess it…

Hi Michael,

Michael Van Canneyt wrote
Longword used to be Cardinal. I guess it was changed for Delphi compatibility.

I really like Sven's idea of using (U)IntX data types where X is 8, 16, 32 or 64 bit. I think this is also future proof, considering Delphi's data type mess and the fact that FPC likes to be FPC compatible.

With that being said, I noticed the FPC Language Reference doesn't mention the (U)IntX data it not maybe be useful in updating Tables 3.1 & 3.2 with the (U)IntX data types?

http://www.freepascal.org/docs-html/ref/refsu5.html

Or maybe add a new table that shows the mapping between (U)IntX and other Object Pascal types and what range they apply to (similar to Table 3.2).

eg: Int16 = SmallInt
UInt16 = Word
Int32 = Cardinal = LongWord
etc.

I don't mind supplying a documentation patch for you to review.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Nikolay Nikolov
to Marco van de Voort: In our previous episode, Graeme Geldenhuys said: Cardinal is the Wirthian designation for…
Marco van de Voort wrote 9 lines
In our previous episode, Graeme Geldenhuys said: > Just curious. What is the history behind the Cardinal data type. As per > the FPC documentation, it is always mapped to the LongWord type. I > presume it is the same in Delphi. Cardinal is the Wirthian designation for the default unsigned integer, just like "integer" is for signed. The Delphi side of things is more convoluted because pre-int64 Delphis had 31-bits Cardinals.

Even more so, Delphi 1 was 16-bit and its Cardinal type was 16-bit (i.e. equal to the "Word" type) With Delphi 2 (the first 32-bit Delphi), Cardinal became 32-bit (31-bit, actually, as Marco said).

So, back then it was a CPU-specific unsigned integer type (just like "Integer" is the signed version).

Note that even though FPC now also supports 16-bit x86 CPUs, Cardinal is still 32-bit unsigned there. Even though this is not Delphi 1 compatible, changing Cardinal to 16-bit does more harm that good. Many FPC demos, such as fpctris and samegame now run unmodified on i8086-msdos. If we changed the Cardinal type to 16-bit, they would break and require changes in order to work. And most 16-bit code that is likely to be ported to FPC is coming from Turbo Pascal, which didn't have Cardinal (only "Word", which is always 16-bit), so we don't really follow the convention that Cardinal is a platform specific type. So, in FPC it is fixed to 32-bit unsigned on all platforms and in all compiler modes.

Nikolay

Marco van de Voort
to Sven Barth: Am 29.03.2016 17:27 schrieb "Graeme Geldenhuys" < I usually use LongWord, too, but with…

In our previous episode, Sven Barth said:

Show quoted text 9 lines
> types with fields of type Word, Smallint etc, than then some Cardinal > fields got mixed in too. I would normally use LongWord instead of > Cardinal to keep to a consistent naming convention. But from your > comments Cardinal has a long history in Pascal. I usually use LongWord, too, but with the recent discovery that in Delphi LongWord is not always 32-bit (and my tendency to confuse Short and SmallInt) I'm inclined to use the (U)IntX (with X being a element of [8, 16, 32, 64]) types to avoid any confusion and surprises.

Apparently Embarcadero knew that too, since (with iirc XE2) they added all variants to Delphi. FPC supports this for some releases already too (and longer in ctypes)

I always found specially small and short very confusing so I adopted it early.

Marco van de Voort
to Graeme Geldenhuys: Thanks Marco, that fulfils my curiosity. :) On a side note: The reason I asked this…

In our previous episode, Graeme Geldenhuys said:

But from your comments Cardinal has a long history in Pascal.

It is the base type of Pascal sucessor Modula 2. (well, in all caps, since it is a case sensitive language)

GNU Pascal also uses it heavily, but their help
http://www.gnu-pascal.de/gpc/Cardinal.html seems to indicate it is not in the Pascal standards.

But many dialects imported features from M2, like e.g. the unit system, and it seems to be a common convention for it to be unsigned as in M2.

But as always with extensions/backports, the exact definition is typically not specified.

But usually it is some unsigned main type probably because in Modula2 INTEGER is the signed complement to basetype CARDINAL, so it makes sense to keep them paired and reverse them in Pascal. Combinations (SHORT, LONG etc) exist too, some M2 dialects abbreviated CARDINAL combinations to -CARD like LONGCARD, some keep it long as LONGCARDINAL.

All -word named types are OS dependent, and systematically wrong on 32+ systems. This because the word=16-bit convention is a 16-bit DOS one, that stuck because of evolution via win16 to win32/64. Also the old conventions of having a very big base type and subtype it as needed is a bit dated.

Moreover since shorter types are not always faster, I think it is better to forget all this, and in new code use INTEGER for the variable types, where range doesn't matter (much) and (u)int<xx> for the rest.

From a language design viewpoint I would add CARDINAL for unsigned integers

variable types, but since it has a fixed type history in Delphi, it is better not to. It isn't needed that much anyway, and for the most common use, API interfacing fixed types or ctypes types are usually better.

Graeme Geldenhuys
to Marco van de Voort: In our previous episode, Graeme Geldenhuys said: It is the base type of Pascal sucessor…

Thanks Marco, interesting history lesson. ;-)

Marco van de Voort wrote
Moreover since shorter types are not always faster, I think it is better to forget all this, and in new code use INTEGER for the variable types, where range doesn't matter (much) and (u)int<xx> for the rest.

I already tend to use Integer for most code, but the code I'm currently working on has an extensive amount of record structures used to read a complex binary data file. The documentation for the data file is primarily in C and uses types like SHORT, USHORT, LONG etc. These translated easily to the SmallInt, Word, LongWord etc types, but as already mentioned in can get confusing keeping track of valid ranges and occasional programmer error.

So I definitely see the benefit in using (U)Int<xx> style data types. They are a lot more obvious [to the programmer] regarding data ranges and byte size.

I was just surprised not to find any reference to them in the FPC documentation. I already made personal annotations about them so as not to be forgotten, but I think it will be beneficial to have them officially included in the FPC Language Reference too. After all, they are part of the System unit.

Here is an example of the annotation I added to my own documentation.

Type Range Size in bytes ──────────────────────────────────────────────────────────────────── Int8 = ShortInt -128 .. 127 1 Int16 = SmallInt -32768 .. 32767 2 Int32 = LongInt -2147483648 .. 2147483647 4 Int64 -9223372036854775808 .. 9223372036854775807 8

UInt8 = Byte 0 .. 255 1 UInt16 = Word 0 .. 65535 2 UInt32 = Cardinal 0 .. 4294967295 4 UInt64 = QWord 0 .. 18446744073709551615 8 ────────────────────────────────────────────────────────────────────

Regards,
- Graeme -

Dmitry Boyarintsev
to Graeme Geldenhuys

On Tue, Mar 29, 2016 at 9:06 PM, Graeme Geldenhuys <

Show quoted text 6 lines
wrote: So I definitely see the benefit in using (U)Int<xx> style data types. They are a lot more obvious [to the programmer] regarding data ranges and byte size.

Does, it also make the code less high-level?
Didn't high level use the platform independent notation such as "int" or "word" to be portable across different platforms back in 60s 70s? At that time word size might vary dramatically from system to system ( https://en.wikipedia.org/wiki/Word_(computer_architecture) ) Thus a code written like this:

  a: Int32;

would not be portable, since it requires a target platform to support 32-bit word (or at least the compiler had to be smart enough).

The modern generation of developers doesn't really have to deal with that too much, due to dominance of 32-bit (as well as virtual machines, such as java and/or .net).
But jump to 64-bit still caused a bit of confusion (in C/C++ and object pascal). with type names and sizes.

thanks,
Dmitry

Florian Klaempfl
to Graeme Geldenhuys: Thanks Marco, interesting history lesson. ;-) I already tend to use Integer for most…
Graeme Geldenhuys wrote 11 lines
Thanks Marco, interesting history lesson. ;-) On 2016-03-29 22:16, Marco van de Voort wrote: > Moreover since shorter types are not always faster, I think it is better to > forget all this, and in new code use INTEGER for the variable types, where > range doesn't matter (much) and (u)int<xx> for the rest. I already tend to use Integer for most code, but the code I'm currently working on has an extensive amount of record structures used to read a complex binary data file. The documentation for the data file is primarily in C

In this case, you should probably use the types from the ctypes unit.

and uses types like SHORT, USHORT, LONG etc. These translated easily to the SmallInt, Word, LongWord etc types,
Martin Schreiber
to Graeme Geldenhuys: My preference is based on the fact that they often translate nicely from C code examples…
Graeme Geldenhuys wrote 6 lines
> I'm inclined to use the (U)IntX (with X being a element of [8, > 16, 32, 64]) types to avoid any confusion and surprises. That's not a bad idea either... I'll look into that for future code.

In MSElang the base types in unit "systypes" are named "int8", "int16", "int32", "int64",
"card8", "card16", "card32", "card64".
Floats are "flo32" and "flo64".
For strings MSElang has
"string8" (utf-8), "string16" (utf-16), "string32" (UCS4) and "string" (any 8 bit encoding or binary data).
The variable size types (integer, cardinal, real) can be defined in "system".

https://gitlab.com/mseide-msegui/mselang/wikis/home

Martin

Mark Morgan Lloyd
to Marco van de Voort: In our previous episode, Graeme Geldenhuys said: It is the base type of Pascal sucessor…
Marco van de Voort wrote
Moreover since shorter types are not always faster, I think it is better to forget all this, and in new code use INTEGER for the variable types, where range doesn't matter (much) and (u)int<xx> for the rest.

Seems eminently sensible to me.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Graeme Geldenhuys
to Dmitry Boyarintsev: On Tue, Mar 29, 2016 at 9:06 PM, Graeme Geldenhuys < Does, it also make the code less…
Dmitry Boyarintsev wrote
Does, it also make the code less high-level?

In my case I'm specifically referring to the benefit of using (U)Int<x> style data types for use in record structures when reading binary data files. In this case, no matter the platform, the data structures must stay a set size.

For any other general coding and variables I use Object Pascal types like Integer.

At that time word size might vary dramatically from system to system ( https://en.wikipedia.org/wiki/Word_(computer_architecture) )

Interesting. I never knew Word was platform dependant. I see even for ARMv1, ARMv6 and ARMv8 the size of Word changes.

Does FPC follow that platform rule, or does FPC always define Word as 16-bits? [sorry I don't have a ARM device to test on at the moment] If Word size does changes in FPC (for example between x86 & ARMv6), then I have quite a bit of code to fix up.

Regards,
- Graeme -

Dmitry Boyarintsev
to Graeme Geldenhuys

On Wed, Mar 30, 2016 at 4:37 AM, Graeme Geldenhuys <

Show quoted text 6 lines
wrote: In my case I'm specifically referring to the benefit of using (U)Int<x> style data types for use in record structures when reading binary data files.

Makes sense.

Show quoted text 5 lines
Does FPC follow that platform rule, or does FPC always define Word as 16-bits? [sorry I don't have a ARM device to test on at the moment] If Word size does changes in FPC (for example between x86 & ARMv6), then I have quite a bit of code to fix up.

Word is always 16-bit.
As Nikolay mentioned, the choice was made by Borland to keep word 16bit even for 32-bit platforms.
GNU Pascal have Word 32-bit (http://www.gnu-pascal.de/gpc/Word.html)

Not sure if FPC support 32-bit in gnu mode. But ISO mode seems to keep it at 16bit.

thanks,
Dmitry

Marco van de Voort
to Dmitry Boyarintsev: On Tue, Mar 29, 2016 at 9:06 PM, Graeme Geldenhuys < Does, it also make the code less…

In our previous episode, Dmitry Boyarintsev said:

Show quoted text 8 lines
> So I definitely see the benefit in using (U)Int<xx> style data types. > They are a lot more obvious [to the programmer] regarding data ranges > and byte size. > Does, it also make the code less high-level? Didn't high level use the platform independent notation such as "int" or "word" to be portable across different platforms back in 60s 70s?

Maybe in theory, and even then only if you include <32-bit targets.

Moreover that was just a minor help anyway, and even in old times (80s,90s) most people fixated their types anyway to make sure the type was large enough.

And then there is the fact that in FPC integer is mode dependent rather than being the best (speediest) type for calculation on the target hardware.

Sven Barth
to Graeme Geldenhuys: In my case I'm specifically referring to the benefit of using (U)Int<x> style data types…

Am 30.03.2016 10:37 schrieb "Graeme Geldenhuys" <

Show quoted text 6 lines
: > At that time word size might vary dramatically from system to system ( > https://en.wikipedia.org/wiki/Word_(computer_architecture) ) Interesting. I never knew Word was platform dependant. I see even for ARMv1, ARMv6 and ARMv8 the size of Word changes.

One needs to differentiate here. In the contexts of CPUs a Word usually means the native register width. The "Word" in Pascal is merely the name of a type. While it might have been originally intended to match the CPU's Word that got lost with Borland's introduction of 32-bit Pascal.

Does FPC follow that platform rule, or does FPC always define Word as 16-bits? [sorry I don't have a ARM device to test on at the moment] If Word size does changes in FPC (for example between x86 & ARMv6), then I have quite a bit of code to fix up.

Word is 16-bit in FPC.

Regards,
Sven