Sign in Join

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

Mailing lists / fpc-pascal / 2023-06

Pchar from constant string

9 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Hairy Pixels

What is really happening in this snippet? I think it must be implicitly taking the address of the constant string but is it also adding the null terminator automatically? The string prints with writeln so it must be null terminated right?

var
  p: Pchar;
begin
  p := '123';
  writeln(p);

Regards,
Ryan Joseph

Mattias Gaertner
to Hairy Pixels
Show quoted text 10 lines
What is really happening in this snippet? I think it must be implicitly taking the address of the constant string but is it also adding the null terminator automatically? The string prints with writeln so it must be null terminated right? var p: Pchar; begin p := '123'; writeln(p);

AFAIK the trailing #0 is already stored in the binary.

Mattias

Michael Van Canneyt
to Mattias Gaertner
Mattias Gaertner wrote 15 lines
On Thu, 29 Jun 2023 21:18:44 +0700 Hairy Pixels via fpc-pascal wrote: > What is really happening in this snippet? I think it must be > implicitly taking the address of the constant string but is it also > adding the null terminator automatically? The string prints with > writeln so it must be null terminated right? > > var > p: Pchar; > begin > p := '123'; > writeln(p); AFAIK the trailing #0 is already stored in the binary.

Yes, it is:

---
_$PROGRAM$_Ld1:
# [4] p := '123';
.ascii "123\000"
.Le11:
---

Just as it is for a shortstring and ansistring:
---
# [6] s:='456';
.ascii "\003456\000"
.Le12:
.size _$PROGRAM$_Ld2, .Le12 - _$PROGRAM$_Ld2
---

Michael.

Tomas Hajny
to Mattias Gaertner: On Thu, 29 Jun 2023 21:18:44 +0700 AFAIK the trailing #0 is already stored in the binary.…
Mattias Gaertner wrote 15 lines
On Thu, 29 Jun 2023 21:18:44 +0700 Hairy Pixels via fpc-pascal wrote: > What is really happening in this snippet? I think it must be > implicitly taking the address of the constant string but is it also > adding the null terminator automatically? The string prints with > writeln so it must be null terminated right? > > var > p: Pchar; > begin > p := '123'; > writeln(p); AFAIK the trailing #0 is already stored in the binary.

Indeed - all constant strings are already terminated with #0. Note that this is not guaranteed for all string variables per se.

Tomas

Hairy Pixels
to Michael Van Canneyt: Yes, it is: --- _$PROGRAM$_Ld1: # [4] p := '123'; .ascii "123\000" .Le11: --- Just as it…
Show quoted text 17 lines
On Jun 29, 2023, at 9:31 PM, Michael Van Canneyt via fpc-pascal wrote: Yes, it is: --- _$PROGRAM$_Ld1: # [4] p := '123'; .ascii "123\000" .Le11: --- Just as it is for a shortstring and ansistring: --- # [6] s:='456'; .ascii "\003456\000" .Le12: .size _$PROGRAM$_Ld2, .Le12 - _$PROGRAM$_Ld2

That's why that worked. Hmm with short strings the null terminator could be truncated when copying right? Something to look out for.

Regards,
Ryan Joseph

Hairy Pixels
to Hairy Pixels
On Jun 30, 2023, at 9:03 AM, Hairy Pixels wrote: That's why that worked. Hmm with short strings the null terminator could be truncated when copying right? Something to look out for.

this is what I meant about truncation. S is no longer null terminated and now the pchar will fail when passed to C libraries right?

var
  s: String;
  p: Pchar;
begin
	s := 'hello';
	p := @s;

Regards,
Ryan Joseph

Michael Van Canneyt
to Hairy Pixels
Hairy Pixels wrote 14 lines
> On Jun 30, 2023, at 9:03 AM, Hairy Pixels wrote: > > That's why that worked. Hmm with short strings the null terminator could be truncated when copying right? Something to look out for. this is what I meant about truncation. S is no longer null terminated and now the pchar will fail when passed to C libraries right? var s: String; p: Pchar; begin s := 'hello'; p := @s;

S will still be null-terminated for ansistrings and shortstrings.

change to

   s:=s+s;
   ; // and not @s
   writeln(p[Length(s)+1]=#0);

and it will print TRUE.

Michael.

Michael Van Canneyt
to Michael Van Canneyt
Michael Van Canneyt wrote 28 lines
On Fri, 30 Jun 2023, Hairy Pixels via fpc-pascal wrote: > > >> On Jun 30, 2023, at 9:03 AM, Hairy Pixels wrote: >> >> That's why that worked. Hmm with short strings the null terminator could >> be truncated when copying right? Something to look out for. > > this is what I meant about truncation. S is no longer null terminated and > now the pchar will fail when passed to C libraries right? > > var > s: String; > p: Pchar; > begin > s := 'hello'; > p := @s; S will still be null-terminated for ansistrings and shortstrings. change to s:=s+s; ; // and not @s writeln(p[Length(s)+1]=#0);

this should have been p[Length(s)] obviously.

Michael.

Tomas Hajny
to Michael Van Canneyt: S will still be null-terminated for ansistrings and shortstrings. change to s:=s+s; ; //…
Michael Van Canneyt wrote 29 lines
On Fri, 30 Jun 2023, Hairy Pixels via fpc-pascal wrote: > > >> On Jun 30, 2023, at 9:03 AM, Hairy Pixels >> wrote: >> >> That's why that worked. Hmm with short strings the null terminator >> could be truncated when copying right? Something to look out for. > > this is what I meant about truncation. S is no longer null terminated > and now the pchar will fail when passed to C libraries right? > > var > s: String; > p: Pchar; > begin > s := 'hello'; > p := @s; S will still be null-terminated for ansistrings and shortstrings. change to s:=s+s; ; // and not @s writeln(p[Length(s)+1]=#0); and it will print TRUE.

However, there are operations valid for Pascal shortstrings which would break this - as an example, older Pascal code used to change the S[0] (i.e. the length byte) for a shortstring which wouldn't ensure that #0 follows such a moved end of the Pascal shortstring.

Moreover, note that #0 is a valid character in Pascal strings, i.e. in general it is _not_ guaranteed that the trailing #0 after the end of the string is the first one encountered when passing the string to a C code. Obviously, you can ensure this in your own code, but it's important to stress that neither the compiler nor the FPC RTL check or enforce full equivalence of Pascal strings and C null-terminated strings.

Tomas