What does "LOCAL" mean, exactly?

Started by mr_unreliable, May 15, 2024, 11:03:19 AM

Previous topic - Next topic

mr_unreliable

Hello Group,

This question was prompted by the following code:


Local inPgWd as Single : inPgWd = 8.5 - oPrn.RightMargin - oPrn.LeftMargin  ' assume 8.5 x 11
Local inFreeSp as Single : inFreeSp = inPgWd - inWidth  ' wd of text
Local inLeftSp as Single : inLeftSp = (inFreeSp / 2) - 0.2  ' fudge (local not working)

      oPrn.Text_Out(&oPrn, inLeftSp + oPrn.inCurX, oPrn.inCurY, TRIM$(sOutLine$))

      oPrn.Set_Font(&oPrn, hMonoSpFont)  ' set normal font


    ' testing for underline (header only)...
    ELSEIF (INSTR(sOutLine$, "----------")) then  ' underline, so draw a line

       ' use the left-hand fudge factor previously declared...
       oPrn.Draw_Line(&oPrn, (inLeftSp+oPrn.inCurX)-0.25, oPrn.inCurY + 0.2, inWidth + 0.5, 4, crBlack)

    ' Check for section title...
    ELSEIF (INSTR(sOutLine$, "EQUITIES") _


PellesC (v6.5) throws an error, the second instance of "inLeftSp" is not defined (the draw_line stmt).  So I changed the Local to Global and went on, BUT...

Why the error?  The help file says that a Local declaration should be good for the entire subroutine.  In this case, it was only good for the one segment of an extended "if" statement.

Granted, I am using a four-year-old version of BCX and PellesC, but I'm not aware of the Local declaration changing that much in those four years.

You may be disparaging me for practicing "declarations-on-the-fly" (i.e., putting in a declaration whenever a new variable is introduced), rather than the more common practice of sweeping up the declarations and placing them all first in the subroutine.

If that's the answer, then the help file should say that.

cheers, mru

MrBcx

LOCAL is a scope of variable where the identifier is only recognized in the SUB or FUNCTION that it appears in.
LOCAL variables are allocated / deallocated from the stack at runtime.

Having GLOBAL and LOCAL variables sharing the exact same name is generally allowed but might cause problems.

There is not enough info for me to diagnose your problem.

Please provide a small and complete example of a SUB or FUNCTION containing the line or lines that are
causing your problems and I'll have a look.




morgan

local exist only in its scope
each 'if' segment
is a new scope

you declared the local
in one scope
when you started a new 'else if'
the previous scope was closed.

this is normal, desired and expected behave.

you should declare it before the if  chain

mr_unreliable

A test case may be found in "bcxPrint_moRpt.zip", located here:

https://bcxbasiccoders.com/smf/index.php?action=dlattach;topic=1038.0;attach=1307

Go to the include file named: Print_IFPS_Report.bas.

Change the declaration on line 229 from Global to Local.

Then you should get an error pointing to line 249, saying that "inLeftSp" was not declared,
  -- at least I did.

cheers, mru

p.s. If "Morgan" is correct, then the help file should be changed.  Local only applies to "scope"
which may be just a "segment" of an if statement -- not the subroutine.

Robert

Quote from: mr_unreliable on May 15, 2024, 04:51:11 PM
A test case may be found in "bcxPrint_moRpt.zip", located here:

https://bcxbasiccoders.com/smf/index.php?action=dlattach;topic=1038.0;attach=1307

Go to the include file named: Print_IFPS_Report.bas.

Change the declaration on line 229 from Global to Local.

Then you should get an error pointing to line 249, saying that "inLeftSp" was not declared,
  -- at least I did.

cheers, mru

p.s. If "Morgan" is correct, then the help file should be changed.  Local only applies to "scope"
which may be just a "segment" of an if statement -- not the subroutine.

Hi mru:

morgan is correct.

Quote

The scope of any identifier declared inside a compound statement, including function bodies, or in any expression, declaration, or statement appearing in if, switch, for, while, or do-while statement(since C99), or within the parameter list of a function definition begins at the point of declaration and ends at the end of the block or statement in which it was declared.


quoted from

https://en.cppreference.com/w/c/language/scope


Thanks for reporting your concern.

I will expand the 'Declaring Local Variables' section to encompass "any expression, declaration, or statement appearing in if, switch, for, while, or do-while statement (since C99), or within the parameter list of a function definition".

mr_unreliable

I would also suggest adding a bit of free advice:

"It is strongly suggested to gather up all your declarations and place them at the beginning of your
sub or function.  This is to avoid any 'scope' issues."

Or something to similar effect.

cheers, mru

MrBcx

Quote from: mr_unreliable on May 16, 2024, 05:26:24 PM
I would also suggest adding a bit of free advice:

"It is strongly suggested to gather up all your declarations and place them at the beginning of your
sub or function.  This is to avoid any 'scope' issues."

Or something to similar effect.

cheers, mru

mr_unreliable,

That advice will go over like a lead balloon for many, including me.  There's nothing inherently wrong or dangerous
with your strategy.  In fact, I've personally used it many times.  I don't believe that advice belongs in the help file.

Be aware that many programs are written where local, scoped variables get allocated and deallocated
inside various blocks like IF-THEN statements, SELECT CASE structures, and every kind of loop.  This can be seen
throughout the source code for the BCX Translator itself and numerous apps written for it. 

Scope is something to be learned, not feared.