Warnings for system.str

Viewed 204

If you compile the following program with Delphi 10.2.3 Tokyo

{$apptype console}
var
  spi: string;
begin
  str(pi:10:5, spi);
  writeln(spi);
end.

then you get the warning:

tst.pas(5) Warning: W1057 Implicit string cast from 'ShortString' to 'string'

although spi is declared as string and the prototype of system.str also has a string (according to http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.Str and the online help):

procedure Str(const X [: Width [:Decimals]]; var S: String);

but the actual code with debug dcu calls this function:

function _Str2Ext(val: Extended; Width, Precision: Integer): _ShortStr;

Obviously the compiler does some kind of magic here, but is this a bug in the documentation or in compiler?

How can I get rid of this warning by coding (not by suppressing warnings), the first try

str(pi:10:5, ShortString(spi));

will throw an error message:

tst.pas(5) Error: E2064 Left side cannot be assigned to

Interestingly there is no Left side.

1 Answers

The compiler is indeed doing some "magic" behind the scenes.

STR is a very old library routine. It's been around since the Turbo Pascal days. When it was created, the only strings were ShortStrings. Of course, in those days, they were just called strings.

The routine does not use the standard syntax for calling procedures or functions in Delphi, and so the compiler does "magic" to convert it internally to a standard function call, and that function returns a ShortString as it always has. That result is then implicitly converted to a string, and that is triggering the warning.

In order to avoid the warning, you can call the routine with an actual ShortString, and then convert it explicitly to a string.

var
  aShortString : ShortString;
  aString      : string;
begin
  str ( pi:10:5, aShortString );
  aString := string(aShortString);
  writeln ( aString );

Or you could skip using STR altogether and use a more modern approach:

uses
  System.SysUtils;
var
  S : string;
begin
  S := Format ( '%10.5f', [ pi ] );
  writeln ( S );

The STR routine is still supported for backward compatibility. Personally, I use this routine in code I wrote in 1984 that is still a part of my modern Delphi application today.

Related