Did I catch your attention? I guess I did if you are reading this. Just to be clear, I don’t hate integers — I hate using integers (a.k.a. signed numbers) where they don’t make sense. For example let’s take the standard intrinsic routine called Length (in System unit). It returns the length of an array (or string) in format of a signed 32-bit integer. While I doubt anyone will use 2 gigs of memory for an array, this still breaks the prettyness of the code. Almost all routines that need an unsigned integer still require a signed one. And this is not limited only to Delphi — most of the .NET libraries use “int” when they should use “uint” (I’m not even going to mention Java here! Last time I checked there was no concept of “unsigned” in it).
Anyway, being as I am, I always try to use the Cardinal type when I do not require the negative values. For instance iterating in a FOR loop from 0 (zero) to a length of an array. This doesn’t benefit me in any way, aside of personal satisfaction. It even tends to “bite me in the ass” sometimes. Let’s take this example:
function MakeString(const AChar: Char; const ACount: Cardinal): String; var I: Cardinal; begin Result := ''; for I := 0 to ACount - 1 do Result := Result + AChar; end; begin WriteLn('Str1 = ', MakeString('A', 2)); WriteLn('Str2 = ', MakeString('B', 0)); ReadLn; end.
What will this program write on the console? I bet you though it would be: “Str1 = AA” and “Str2 = “. Think again, but this time harder.
Now let me explain what is really going on:
- I pass 0 as the ACount parameter to the MakeString function.
- I use a Cardinal data type for my FOR loop.
- I start at 0 and go to ACount – 1.
- ACount being 0, the upper bound of the FOR loop becomes (0 – 1) =4294967295.
- The FOR loop continues for a lot of iterations.
- You will either run out of memory or get bored waiting for a result…
- If I were an Integer the loop would have worked flawlessly.
“I hate integers …”