Search code examples
delphifreepascallazarus

Why do the Delphi and FreePascal compilers handle 0-based and x-based static arrays differently?


program test;

uses
  sysutils;

const
  BUFLEN = 20;

var
  Buf0: array[0..BUFLEN-1] of char;
  Buf1: array[1..BUFLEN] of char;
  s: string;

begin
    // Fillchar...
    // StrPLCopy...

    SetString(s, Buf1, Length(Buf1));
    // Error: Incompatible type for arg no. 2: Got "Array[1..20] Of Char", expected "PChar"

    SetString(s, Buf0, Length(Buf0));
    // compiles ok
end.

In C/C++, we use array names as pointers very often. In Delphi, we can also implement this like the example above.

Though, using the Buf1 array in FreePascal's SetString() causes an error, while the Buf0 array works just fine. An array's base index shouldn't matter, right?

Is there any documentation that justifies this behaviour?

Tested in FPC 3.0.4 and Delphi 10.3.


Solution

  • If you look at the definition you link to, the 2nd argument can be one of the following types:

      Buf: PAnsiChar;
      Buf: PWideChar;
      Buf: PChar;
      Buf: PUnicodeChar;
      Buf: PChar;
      Buf: PWideChar;
      Buf: PChar;
    

    If you remove the duplicates / aliases, you get the following possibilities:

      Buf: PAnsiChar;
      Buf: PWideChar;
      Buf: PUnicodeChar;
    

    In the {$X+} state, there is a built-in type compatibility between:

    PAnsiChar <-> ARRAY[0..nn] OF AnsiChar
    PWideChar <-> ARRAY[0..nn] OF WideChar
    PUnicodeChar <-> ARRAY[0..nn] OF UnicodeChar
    

    As you can see above, all the Char arrays that are compatible with PChar-types all have a lower index of 0. That's just how the compiler type compatibility works. The reason for this is that it this type compatibility mainly is for easier conversion of C(++) code, and C(++) doesn't have the ability to specify a lower limit of (ordinary) arrays - they are always 0.

    So the same is done in Delphi / FreePascal in order to remain (as much as possible) compatible with C(++).