LOCAL_VAR v's STACK_VAR
cmatkin
Senior Member
Hi,
I have been given a task to update some of my colleagues Netlinx code.
I found that in most of is define_calls he has created a local_var?s called loop.
Eg:
DEFINE_CALL ?something?
{
LOCAL_VAR loop
..code..
}
DEFINE_CALL ?something 2?
{
LOCAL_VAR loop
..code..
}
Would it be better to convert these to STACK_VAR?s as this are not static once created?
Eg:
DEFINE_CALL ?something?
{
STACK_VAR loop
..code..
}
DEFINE_CALL ?something 2?
{
STACK_VAR loop
..code..
}
Regards
Craig
I have been given a task to update some of my colleagues Netlinx code.
I found that in most of is define_calls he has created a local_var?s called loop.
Eg:
DEFINE_CALL ?something?
{
LOCAL_VAR loop
..code..
}
DEFINE_CALL ?something 2?
{
LOCAL_VAR loop
..code..
}
Would it be better to convert these to STACK_VAR?s as this are not static once created?
Eg:
DEFINE_CALL ?something?
{
STACK_VAR loop
..code..
}
DEFINE_CALL ?something 2?
{
STACK_VAR loop
..code..
}
Regards
Craig
Comments
-
"It depends" :-)
a LOCAL_VAR is working within a function block (Call, Function, but also i.e. in a CASE, PUSH of BUTTON_EVENT, etc). It will still hold its value if the if the function block if finished. It is hold in the nonvaltile memory of a master
a STACK_VAR is working in most situations like a LOCAL_VAR, but will lost its value after the section is done. It is hold in the volatile memory of the master.
There are some situations where by design a STACK_VAR will not work, i.e. if you need the value of the STACK_VAR in a WAIT. (the functions within the wait are stacked, but the stack_var content is lost because the function block of the code is finished). There are some more exceptions where a LOCAL_VAR must be used instead of a STACK_VAR (some by design, some more like a bug ;-) -
I prefer to make my subroutine variables stack whenever I can. For one, you have far less non-volatile memory than volatile, and I have run out on big projects with a lot of modules. Second, stack variable reset to null every time the routine is called. Sure, you can just initialize it, but one line less code, is one thing less to worry about.
Of course, there are time you need it to be a local. If the routine is tracking something that only it needs to know about, you probably want it to retain it's value. And, as mentioned, you must make any variable used in a wait a local. -
I have to admit that I never use STACK_VARs or LOCAL_VARsDHawthorne wrote:I prefer to make my subroutine variables stack whenever I can. For one, you have far less non-volatile memory than volatile, and I have run out on big projects with a lot of modules. Second, stack variable reset to null every time the routine is called. Sure, you can just initialize it, but one line less code, is one thing less to worry about.
Of course, there are time you need it to be a local. If the routine is tracking something that only it needs to know about, you probably want it to retain it's value. And, as mentioned, you must make any variable used in a wait a local. -
Local Variables
Functions should be designed to be some what portable. With this in mind, using Local_Vars to keep the last value is normally not the best practice. Although most programmer use Local_Vars and reset them at the beginning of each function. In this case Stack_Vars should be used. Stack_Vars allocate memory from the stack whenever the function is called, and at the end it de-allocates the memory. This tends to manage your memory better. If you truly need to retain the last value in the function, by all means use Local_Var. By doing this you tend to make the function less portable. I would suggest in this case passing global variables into the function, and let the function use the passed in variables. This way the function can be used for multiple object instances.
The biggest plus for Local_Vars is you can actually watch them in debug. I tend to make them Local_Vars for testing, and then switch them back to Stack_Vars when the function is debugged. By the way you can actually watch Stack_Vars in debug, but only when you have a break point inside the scope of the Stack_Var. This is assuming you can actually get break points to work. -
ericmedley wrote:I have to admit that I never use STACK_VARs or LOCAL_VARs
The you are using LOCAL_VARs. That's the default if no explicit declaration is made. I generally try to make all my declarations explicit so there is no confusion what type of memory space is being used, or on the outside chance the default ever gets changed in the compiler. -
Yes, that's what the help file states:DHawthorne wrote:The you are using LOCAL_VARs. That's the default if no explicit declaration is made.
However, I believe the help file is in error and is in fact the other way around. Consider the following code:Netlinx help file wrote:If neither the LOCAL_VAR nor the STACK_VAR keyword is specified, LOCAL_VAR is assumed.DEFINE_DEVICE dvTP = 10001:1:0 DEFINE_FUNCTION fnVarTest() { INTEGER a STACK_VAR INTEGER b LOCAL_VAR INTEGER c a++ b++ c++ SEND_STRING 0, "'a=',ITOA(a),' b=',ITOA(b),' c=',ITOA(c)" } DEFINE_EVENT BUTTON_EVENT[dvTP,1] { PUSH: { fnVarTest() } }Pushing button 1 four times produces this output:
Line 1 :: a=1 b=1 c=1 - 15:24:48
Line 2 :: a=1 b=1 c=2 - 15:24:49
Line 3 :: a=1 b=1 c=3 - 15:24:50
Line 4 :: a=1 b=1 c=4 - 15:24:51
The only variable that maintains its value is the variable that is explicitly declared as a LOCAL_VAR. If not specified, the variable is treated as a STACK_VAR. -
Not necessarily. Maybe eric just never uses variables in his functions, for extra style points.DHawthorne wrote:
Then you are using LOCAL_VARs.ericmedley wrote:I have to admit that I never use STACK_VARs or LOCAL_VARs -
Joe Hebert wrote:The only variable that maintains its value is the variable that is explicitly declared as a LOCAL_VAR. If not specified, the variable is treated as a STACK_VAR.
Nice work Joe.
It actually makes more sense for it to default to stack_var on the principle of least surprise. Least surprise, that is, for anyone who is familiar with many other languages (your mileage may vary.) -
mpullin wrote:Not necessarily. Maybe eric just never uses variables in his functions, for extra style points.
...Or maybe I don't use functions at all... There are other ways to do repetitive things.
8~) -
Something to be aware when using stack vars
http://www.amxforums.com/showthread.php?t=2642
in short - the stack var caused a debgging problems -
and never forget:
STACK_VAR CHAR Arrays[] are not empty, they are initialized with rubbish unless you assign something to them in this way
Array='...'
they are not cleared when you assign
Array[1]=$2
Array[2]=$0D
and so on...
wasted another afternoon because of that, even though i knew before....
i already thought about using STACK_VAR CHAR Arrays as Randomizer... -
REBUILD_EVENT wrote:and never forget:
STACK_VAR CHAR Arrays[] are not empty, they are initialized with rubbish unless you assign something to them in this way
Array='...'
they are not cleared when you assign
Array[1]=$2
Array[2]=$0D
and so on...
wasted another afternoon because of that, even though i knew before....
i already thought about using STACK_VAR CHAR Arrays as Randomizer...
It's more likely they are just allocated, and whatever was in that memory space previously is what you are seeing. However, when stack arrays are initialized, they are initialized with a length of zero, and normal array operations would treat them as empty. It is because you are referencing individual elements that you are seeing anything at all: namely, whatever data is in that space. I suspect this is not limited to stack arrays, but any that is not initialized with an explicit value. -
[QUOTE=However, when stack arrays are initialized, they are initialized with a length of zero, and normal array operations would treat them as empty.[/QUOTE]
SET_LENGTH_STRING(String,0) will set the length to zero, but it does not clear the string value until it is reloaded. I was told, the processor looks at the String Length first, if over 0 then the value. -
I beleive I once heard of something like an "Event Variable?" Is there a variable type that can be defined once at the top of an event and hold value through a PUSH, RELEASE and HOLD without redeclaration and initialization?
Thanks -
I don't think so ("event variable"), but that should definitely go in the suggestion box....
Jeff -
No such animal...
-
TurnipTruck wrote:I beleive I once heard of something like an "Event Variable?" Is there a variable type that can be defined once at the top of an event and hold value through a PUSH, RELEASE and HOLD without redeclaration and initialization?
Thanks
I believe that refers to the built-in ones ... like BUTTON.INPUT.CHANNEL. I could be wrong; that was my understanding of it though. -
I'll vote for the "Event Variable"TurnipTruck wrote:I beleive I once heard of something like an "Event Variable?"
Categories
- All Categories
- 2.5K AMX General Discussion
- 922 AMX Technical Discussion
- 514 AMX Hardware
- 502 AMX Control Products
- 3 AMX Video Distribution Products
- 9 AMX Networked AV (SVSI) Products
- AMX Workspace & Collaboration Products
- 3.4K AMX Software
- 151 AMX Resource Management Suite Software
- 386 AMX Design Tools
- 2.4K NetLinx Studio
- 135 Duet/Cafe Duet
- 248 NetLinx Modules & Duet Modules
- 57 AMX RPM Forum
- 228 MODPEDIA - The Public Repository of Modules for Everyone
- 943 AMX Specialty Forums
- 2.6K AMXForums Archive
- 2.6K AMXForums Archive Threads
- 1.5K AMX Hardware
- 432 AMX Applications and Solutions
- 249 Residential Forum
- 182 Tips and Tricks
- 146 AMX Website/Forums