Forum > Beginners

[Solved] Is it possible to const an argument passed by reference in FPC?

<< < (2/13) > >>

440bx:

--- Quote from: ASerge on July 24, 2019, 11:40:06 am ---Same thing in x32. A short string is passed by reference. There is no allocation and copying inside the function.

--- End quote ---
No.  The reason you are getting that is because you specified "const" in the parameter, which for strings happens to be the same as specifying constref, therefore in that case, it causes the shortstring to be passed by reference but, while const works like constref for strings, it is not a reliable way of passing a parameter by reference.

From the Free Pascal Programmer's reference guide (page 192)
--- Quote ---Remark: Contrary to Delphi, no assumptions should be made about how const parameters are passed to the underlying routine. In particular, the assumption that parameters with large size are passed by reference is not correct. For this the constref parameter type should be used, which is available as of version 2.5.1 of the compiler.
--- End quote ---

That const worked in the example you provided is happenstance.

if you have code like this:
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var  s : shortstring; function DoString(p : string) : boolean;begin  p      := p + 'z';  result := true;end; begin  s := 'abc';   DoString(s);  writeln(s);  // prints abc, proving that the parameter s was passed by value.               // HOWEVER, you are correct that the parameter is passed by reference               // BUT a copy of the parameter is made thus making it the same as being passed by valueend. you'll see that the compiler allocates a copy of the string
--- Code: ASM  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---                                  begin00401560 55                       push   %ebp00401561 89e5                     mov    %esp,%ebp00401563 8da424f8feffff           lea    -0x108(%esp),%esp         ; allocate space for the short string0040156A 8945fc                   mov    %eax,-0x4(%ebp)0040156D 8b4dfc                   mov    -0x4(%ebp),%ecx00401570 8d85f8feffff             lea    -0x108(%ebp),%eax00401576 baff000000               mov    $0xff,%edx0040157B e8300a0000               call   0x401fb0 <fpc_shortstr_to_shortstr>  ; copy it                                   p      := p + 'z';00401580 680cb04000               push   $0x40b00c                 ; address of character 'z"00401585 8d8df8feffff             lea    -0x108(%ebp),%ecx0040158B 8d85f8feffff             lea    -0x108(%ebp),%eax00401591 baff000000               mov    $0xff,%edx00401596 e8a50d0000               call   0x402340 <fpc_shortstr_concat>  ; append character 'z" to COPY of string parameter                                  result := true;0040159B b001                     mov    $0x1,%al                                          end;0040159D c9                       leave  0040159E c3                       ret     In 32bit, the called function copies the string.

In 64bit, here is the code:
--- Code: ASM  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---                                          begin0000000100001610 55                       push   %rbp0000000100001611 4889e5                   mov    %rsp,%rbp0000000100001614 488d6424d0               lea    -0x30(%rsp),%rsp0000000100001619 48895df8                 mov    %rbx,-0x8(%rbp)000000010000161D e87e2c0000               callq  0x1000042a0 <fpc_initializeunits>                                          s := 'abc';0000000100001622 488d05f7b90000           lea    0xb9f7(%rip),%rax        # 0x10000d020 <_$PROGRAM$_Ld2>0000000100001629 488d0dd0d90000           lea    0xd9d0(%rip),%rcx        # 0x10000f000  - address of copy0000000100001630 48baff00000000000000     movabs $0xff,%rdx000000010000163A 4989c0                   mov    %rax,%r8000000010000163D e83e060000               callq  0x100001c80 <fpc_shortstr_to_shortstr>                                          DoString(s);0000000100001642 488d0db7d90000           lea    0xd9b7(%rip),%rcx        # 0x10000f000  - pass the address of the copy0000000100001649 e862ffffff               callq  0x1000015b0 <DOSTRING> The 64bit code, unlike the 32bit code, makes a copy of the string and passes the copy to the function.  In the 32bit code it is the called function that makes a copy of the parameter.

for a C construct that specifies "const" and "&" (reference in C), the equivalent and reliable Pascal construct is "constref".  For strings, const just happens to work but, const may not be equivalent to "const" and "&" for other parameter types.


ETA:

You are correct that using "const" does work in the case of a string but, for anything that is meant to be constant and passed as a parameter, the clean, reliable way is to specify "constref", not const.

marcov:

--- Quote from: 440bx on July 24, 2019, 10:51:45 am ---
--- Quote from: marcov on July 24, 2019, 10:38:47 am ---strings and dynamic arrays already contain an implicit ref.

--- End quote ---
For strings, that is only true when LONGSTRINGS ON is in effect and the parameter is not a shortstring. Otherwise, constref is required to declare the string is passed by reference (instead of value) and that it cannot be modified.

--- End quote ---

Const can also be by reference, if the ABI forces it. But yes, in hypothetical heavy shortstring usage where you want to forcedly avoid the case that it isn't, that is better.

I don't think I used shortstrings for anything in the last decade except maybe an isolated case where I used it as the key of a dictionary.

440bx:

--- Quote from: marcov on July 24, 2019, 12:55:12 pm ---But yes, in hypothetical heavy shortstring usage where you want to forcedly avoid the case that it isn't, that is better.

--- End quote ---
You were correct in what you stated in your first post.  "const" does work for strings to pass them as constants and by reference. I didn't realize that strings were one of the exceptions where "const" is the same as "constref".

From your previous post, I see that we agree on the fact that "constref" is the better and safe way to pass the parameter when const and by reference are needed instead of relying on exceptional cases the compiler makes.

ikel:
Thanks everyone for the clarification.
It seems my takeaway are...


* const on string works as constant and by reference
* prefer constref is the better way to pass parameters when both are needed
@440bx, thanks for the comparison between 32 and 64 bit implementations. Very helpful to see what's happening behind the screen.

I feel working with FPC is a breath of fresh air.

ASerge:
By order. First @marcov say:

--- Quote from: marcov on July 24, 2019, 10:38:47 am ---constref only makes a const argument forcedly by ref, but this is rarely used because strings and dynamic arrays already contain an implicit ref.

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function isValidEntry(const input: string):boolean;
--- End quote ---
You you rejected it:

--- Quote from: 440bx on July 24, 2019, 10:51:45 am ---For strings, that is only true when LONGSTRINGS ON is in effect and the parameter is not a shortstring.

--- End quote ---
And after I made it clear that it was wrong, you agreed with @marcov.

--- Quote from: 440bx on July 24, 2019, 12:51:25 pm ---No.  The reason you are getting that is because you specified "const" in the parameter, which for strings happens to be the same as specifying constref,

--- End quote ---
Good answer :(

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version