Forum > Beginners
[Solved] Is it possible to const an argument passed by reference in FPC?
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