Jens Mühlenhoff
Jens Mühlenhoff

Reputation: 14873

Is there any compiler magic in PChar / PWideChar / PAnsiChar casts?

I often read that the compiler does some kind of magic when casting to PChar.

The main purpose of PChar is to call foreign code in libraries that expect a zero terminated array of characters (C style "string").

PChar is a type that is an alias to PWideChar on Unicode Delphi and an alias to PAnsiChar on non-unicode Delphi.

Delphi strings (string = AnsiString / UnicodeString, I'm not talking about WideString here, let alone ShortString ...) on the other hand have a hidden length instead of a termination char. They are also reference counted and use copy on write.

Are Delphi strings automatically allocated and kept to be one char longer with an implicit #0 char in order to make casting to a PChar (PAnsiChar / PWideChar) easier or does the compiler check and adjust the string when it encounters a conversion to PChar?

Upvotes: 1

Views: 2509

Answers (2)

kludg
kludg

Reputation: 27493

A string variable internally is a pointer into a structure containing prefix, characters and null terminator. Though the structure starts from the prefix (containing string length, ref count, char size and codepage) the pointer points to the first character, so casting to PChar is straightforward.

The magic behind of string -> PChar casting is that always PChar(S) <> nil, even if string is empty (S = '' and Pointer(S) = nil). Instead of returning a string variable pointer 'as is', like Pointer(S) do, PChar(S) calls a function that checks whether Pointer(S) is nil and if Pointer(S) = nil returns a pointer to a dummy empty string instead of nil (i.e. a pointer to the null terminator of the dummy empty string).

Upvotes: 3

David Heffernan
David Heffernan

Reputation: 612794

The process is as follows:

  • If a string s has length greater than zero, then PChar(s) returns a pointer to the first element of the string content. Because the string is managed to have a hidden null-terminator nothing more needs to be done.
  • If a string s has length zero, then PChar(s) returns a pointer to a block of memory containing a null-terminator.

As an implementation detail, the null-terminator that is returned from PChar(nil) is a global constant allocated in the read-only section of the compiled module.

Are Delphi strings automatically allocated and kept to be one char longer with an implicit #0 char in order to make casting to a PChar (PAnsiChar / PWideChar) easier?

Yes.

The magic, if you can call it that, is that:

  1. Using PChar() on empty strings returns a pointer to a null-terminator.
  2. Delphi maintains the hidden null-terminator at the end of the string.

Upvotes: 11

Related Questions