Sign in Join

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

Mailing lists / fpc-pascal / 2017-07

Static local variables available?

8 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

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

Bo Berglund

I am trying to clean up an existing application where handling of incoming serial data is done inside an event function OnRxData() of the serial component.
I want to move the processing into a regular procedure so I can later add a different hardware channel (TCP/IP) as a user choice.

Now when looking at the existing code in the RxData() procedure I see that there is a while loop retrieving one character at a time from the serial port and processing it. In the processing these characters are stuffed into a temp string buffer until the complete packet is ready.

If I divide the single procedure into two where the event procedure would have the while loop extracting the character and then call a handling procedure with the char as argument then the processor cannot have the while, but it must have the buffer...

The only way I could imagine this to work is if:
1) I use a globally defined string variable as buffer
2) It is somehow possible to define the buffer as a static local var.

So since I don't really want to use a global, is it possible to declare a local variable static in the sense that it retains its values across calls to the procedure?
If so how is it done?

Bo Berglund Developer in Sweden
Maciej Izak
to Bo Berglund

2017-07-20 11:03 GMT+02:00 Bo Berglund :

Show quoted text 5 lines
So since I don't really want to use a global, is it possible to declare a local variable static in the sense that it retains its values across calls to the procedure? If so how is it done?
procedure foo;
{$PUSH}
const{$J+}
  s : string ='';
{$POP}
begin
  writeln(s);
  if s = '' then
    s := 'hello from static local variable';
end;
begin
  foo; // will print empty line
  foo; // will print 'hello from static local variable'
  foo; // will print 'hello from static local variable'
end.
Best regards, Maciej Izak
Sven Barth
to Maciej Izak
Maciej Izak wrote 25 lines
2017-07-20 11:03 GMT+02:00 Bo Berglund < >: So since I don't really want to use a global, is it possible to declare a local variable static in the sense that it retains its values across calls to the procedure? If so how is it done? procedure foo; {$PUSH} const{$J+} s : string =''; {$POP} begin writeln(s); if s = '' then s := 'hello from static local variable'; end; begin foo; // will print empty line foo; // will print 'hello from static local variable' foo; // will print 'hello from static local variable' end.

For completeness sake:
https://www.freepascal.org/docs-html/current/ref/refse10.html#x22-210002.2 , especially the remark at the end.

Regards,
Sven

Bo Berglund
to Maciej Izak: 2017-07-20 11:03 GMT+02:00 Bo Berglund : procedure foo; {$PUSH} const{$J+} s : string ='';
Maciej Izak wrote 13 lines
2017-07-20 11:03 GMT+02:00 Bo Berglund : > So since I don't really want to use a global, is it possible to > declare a local variable static in the sense that it retains its > values across calls to the procedure? > If so how is it done? > procedure foo; {$PUSH} const{$J+} s : string =''; {$POP}

Thanks,
but it looks a bit involved, probably better to use an object field variable instead only accessible from the internal methods.

Bo Berglund Developer in Sweden
Sven Barth
to Bo Berglund
"Bo Berglund" wrote 21 lines
On Thu, 20 Jul 2017 11:11:50 +0200, Maciej Izak wrote: >2017-07-20 11:03 GMT+02:00 Bo Berglund : > >> So since I don't really want to use a global, is it possible to >> declare a local variable static in the sense that it retains its >> values across calls to the procedure? >> If so how is it done? >> > >procedure foo; >{$PUSH} >const{$J+} > s : string =''; >{$POP} Thanks, but it looks a bit involved, probably better to use an object field variable instead only accessible from the internal methods.

If you don't want to use $push/$pop then you can also simply enable $J+ for the whole unit. But this will also mean that global constants are writable.

Regards,
Sven

Santiago A.
to Sven Barth
Sven Barth wrote 30 lines
Am 20.07.2017 13:01 schrieb "Bo Berglund" < >: > > On Thu, 20 Jul 2017 11:11:50 +0200, Maciej Izak > < > wrote: > > >2017-07-20 11:03 GMT+02:00 Bo Berglund < >: > > > >> So since I don't really want to use a global, is it possible to > >> declare a local variable static in the sense that it retains its > >> values across calls to the procedure? > >> If so how is it done? > >> > > > >procedure foo; > >{$PUSH} > >const{$J+} > > s : string =''; > >{$POP} > > Thanks, > but it looks a bit involved, probably better to use an object field > variable instead only accessible from the internal methods. If you don't want to use $push/$pop then you can also simply enable $J+ for the whole unit. But this will also mean that global constants are writable.

Well, I'm an old dog so I prefer old fashion ways. A variable that retains its value is, from memory point of view, a global variable. I mean, the memory is never freed, it's not freed when it goes out of scope. So, the problem is what to do to limit the visibility to the procedure.

What about the old interface/implementation ways? You can't limit the visibility to the procedure, but you can limit the visibility to the implementation, so it is globally invisible.

unit hiddenVar;
interface
  procedure foo;
  procedure resetFoo;
implementation
var
 HiddenValue:integer;
procedure foo;
begin
 writeln(HiddenValue);
 inc(HiddenValue);
end;
procedure resetFoo;
begin
 HiddenValue:=0;
end;
initialization
  resetFoo;
end.
Saludos Santiago A.
Sven Barth
to Santiago A.
"Santiago A." wrote 27 lines
El 20/07/2017 a las 15:50, Sven Barth via fpc-pascal escribió: > > Am 20.07.2017 13:01 schrieb "Bo Berglund" : > > > > On Thu, 20 Jul 2017 11:11:50 +0200, Maciej Izak > > wrote: > > > > >2017-07-20 11:03 GMT+02:00 Bo Berglund : > > > > > >> So since I don't really want to use a global, is it possible to > > >> declare a local variable static in the sense that it retains its > > >> values across calls to the procedure? > > >> If so how is it done? > > >> > > > > > >procedure foo; > > >{$PUSH} > > >const{$J+} > > > s : string =''; > > >{$POP} > > > > Thanks, > > but it looks a bit involved, probably better to use an object field > > variable instead only accessible from the internal methods. > > If you don't want to use $push/$pop then you can also simply enable $J+

for the whole unit. But this will also mean that global constants are writable.

Well, I'm an old dog so I prefer old fashion ways. A variable that

retains its value is, from memory point of view, a global variable. I mean, the memory is never freed, it's not freed when it goes out of scope. So, the problem is what to do to limit the visibility to the procedure.

Writable constants *are* the old fashion way, cause this kind of usage stems from Turbo Pascal and allowed to restrict the visibility of symbols.

Regards,
Sven

Unknown author
to Sven Barth
Sven Barth wrote 46 lines
Am 21.07.2017 10:44 schrieb "Santiago A." : > > El 20/07/2017 a las 15:50, Sven Barth via fpc-pascal escribió: >> >> Am 20.07.2017 13:01 schrieb "Bo Berglund" : >> > >> > On Thu, 20 Jul 2017 11:11:50 +0200, Maciej Izak >> > wrote: >> > >> > >2017-07-20 11:03 GMT+02:00 Bo Berglund : >> > > >> > >> So since I don't really want to use a global, is it possible to >> > >> declare a local variable static in the sense that it retains its >> > >> values across calls to the procedure? >> > >> If so how is it done? >> > >> >> > > >> > >procedure foo; >> > >{$PUSH} >> > >const{$J+} >> > > s : string =''; >> > >{$POP} >> > >> > Thanks, >> > but it looks a bit involved, probably better to use an object field >> > variable instead only accessible from the internal methods. >> >> If you don't want to use $push/$pop then you can also simply enable $J+ for the whole unit. But this will also mean that global constants are writable. > > Well, I'm an old dog so I prefer old fashion ways. A variable that retains its value is, from memory point of view, a global variable. I mean, the memory is never freed, it's not freed when it goes out of scope. So, the problem is what to do to limit the visibility to the procedure. Writable constants *are* the old fashion way, cause this kind of usage stems from Turbo Pascal and allowed to restrict the visibility of symbols. Regards, Sven

Except really old fashioned might mean Modula

That's a neat idea to create a new module, and use it sort of like a private object or static object just for the purpose of storing a global variable in the private implementation section.

One disadvantage of modules (units) is that they add extra bytes to the Exe, but is generally not an issue in desktop software. Previously when people have asked for static C type things in fpc they were working with embedded systems where every last byte counted and size of the program was an issue. But, I don't know the use case in this episode..