Hi Franck,
I have to say, I understand your explanation but not the fundamental meaning of it. By inspecting the local variable with gdb, I see you are right. But since I declared the global string variable as a String(40), I expected the capacity passed to the procedure to be 40, not 3, which is the actual length, not the total string capacity . However, I think this is a rather strange behaviour. Why the original string capacity is not passed along with the value? In fact, this means the local string is not the same type as the one I declared globally and passed by value. Am I wrong?
The procedure where I discovered this receives strings of various lengths then it pads them with blanks up to the length of the integer parameter and displays them in reverse video. The original value must not be modified, and it must accept even literals values. So, if I declare a type with a fixed length (capacity), I will not be able to pass strings of various lengths to my procedure anymore... I will go for the local copy solution for now, but I think it would have been a good idea to pass the capacity of the string instead of its actual length...
Thanks for this fast answer
Pascal Viandier pascal@accovia.com
Pascal Viandier wrote:
I just hit something I do not really understand in the way GPC passes parameters to procedures. The following sample program:
Program ParamTest; Var S40 : String(40); I : Integer;
Procedure TstParams(S : String; IL : Integer); Begin WriteLn('Before: S=', S, ' IL=', IL); S := S + 'BBB'; { Using Concat() does the same } IL := IL + 4; WriteLn('After: S=', S, ' IL=', IL); End;
Begin S40 := 'AAA'; I := 4; TstParams(S40, I); End.
Produces the following output: Before: S=AAA IL=4 After: S=AAA IL=8
How come the string cannot be modified inside of the procedure (without impacting the global string) but the integer can? Until now, my understanding of the parameters passing mechanism was that when you pass a parameter by value, the procedure uses a local copy of
it,
and this copy may be modified locally. This mechanism seems to work for integers but not for strings! However, if the string modification is somewhat "illegal" at least GPC
could
issue a compilation warning.
The string can be modified, but not appended to. Value parameters of type `String' (without a given capacity) assume as capacity the length of the actual parameter, in this case 3.
To avoid it, you can declare the parameter of a given capacity, say `String (40)' (via a type-declaration, of course). Then, of course, you have to specify in advance how big the parameter can become. (But otherwise the compiler would have to guess that, that's why it doesn't work like this.)
I would be interested to understand better how this works, because this behavior causes bugs in the programs I am porting from SUN Pascal and perhaps in ways I don't see as clearly as in this example.
I don't know what Sun Pascal does. In Borland Pascal, all strings are limited to 255 chars, so you'd get that effect with `String (255)'.
To avoid artificial limits, it's often useful to declare local variables with a capacity based on the actual parameter, e.g. in your case:
Procedure TstParams(S : String; IL : Integer); Var Tmp: String (Length (S) + 3); Begin Tmp := S; WriteLn('Before: S=', Tmp, ' IL=', IL); Tmp := Tmp + 'BBB'; { Using Concat() does the same } IL := IL + 4; WriteLn('After: S=', Tmp, ' IL=', IL); End;
Or perhaps (depending on what you need):
Var Tmp: String (2 * Length (S));
Frank
-- Frank Heckenbach, frank@g-n-u.de, http://fjf.gnu.de/, 7977168E GPC To-Do list, latest features, fixed bugs: http://www.gnu-pascal.de/todo.html GPC download signing key: ACB3 79B2 7EB2 B7A7 EFDE D101 CD02 4C9D 0FE0 E5E8