# Index array

Junior MemberPosts: 8
I have a array (vector[5]={5,12,11,16,23}).

I need the position the vector for example.

vector[3]=3, vector[1]=1

how get the index of the elements of vector.

• Registered User Posts: 199
Clarify

Do you mean how do you populate the array or how do you recall the array. In your array...

nVector[3]=11
nVector[1]=5

If you can clarify what you need to do I can help a little.
• Formerly Caffeinated Programmer Posts: 1,917
I think you want this:
```DEFINE_FUNCTION INTEGER GetIndex(INTEGER Array[], INTEGER nValue){
STACK_VAR INTEGER x;
STACK_VAR INTEGER y;
x=1;
y=LENGTH_ARRAY(Array);
WHILE(Array[x]<>nValue and x<=y)
x++

IF(x<=y)
Return x;
ELSE
Return 0;
}

```

I make no guarantees to the function as I just wrote it here, so you may need to fix a couple of things, but I think that is the idea you are trying to accomplish.

Jeff
• Junior Member Posts: 2,159
```DEFINE_FUNCTION INTEGER fnGetIndex(INTEGER nArray[], INTEGER nValue){

INTEGER x

FOR (x=1; x<=LENGTH_ARRAY(nArray); x++) {
IF (nArray[x] = nValue) RETURN x
}

RETURN 0

}
```
• Formerly Caffeinated Programmer Posts: 1,917
Use my way if you get paid by the line, use Joe's way if you like to skin cats quicker :P

Jeff

P.S.
I keep forgetting about that approach. Nice code Joe.
• Registered User Posts: 199
question

Joe,

The only question I have with your code is if the same value is in multiple positions then x will change as it runs through the for loop, right?
• Junior Member Posts: 2,159
jazzwyld wrote: »
Joe,

The only question I have with your code is if the same value is in multiple positions then x will change as it runs through the for loop, right?
The code will return the index of the first value that matches in the array.
• Registered User Posts: 199
tested

Joe I just looked through the code again. The While Loop will return the first position, the For loop will return the last position if multiple instances occur, because the while loop is dependent on the finding a match, the for loop will run through its sequence and will keep running until it ends the loop, which means if there are multiple values in there the last position gets returned and sets that variable.
• Junior Member Posts: 2,159
Need to test better
jazzwyld wrote:
the for loop will run through its sequence and will keep running until it ends the loop, which means if there are multiple values in there the last position gets returned and sets that variable.
Hi jazzwyld,

No, that?s not true. As soon as the IF is satisfied the function will exit and RETURN the position, which in this case will always be the first match it finds.

Here is some code that verifies it:
```DEFINE_DEVICE

dvTP = 10001:1:0

DEFINE_CONSTANT

INTEGER nTest[] = {
1,2,3,3,2,1
}

DEFINE_FUNCTION INTEGER fnGetIndex(INTEGER nArray[], INTEGER nValue){

INTEGER x

FOR (x=1; x<=LENGTH_ARRAY(nArray); x++) {
IF (nArray[x] = nValue) RETURN x
}

RETURN 0

}

DEFINE_EVENT

BUTTON_EVENT[dvTP,1] {

PUSH: {

INTEGER x

FOR (x=1; x<=LENGTH_ARRAY(nTest); x++) {
SEND_STRING 0, "'Checking position ',ITOA(x),' -- Index for value ',ITOA(nTest[x]),' = ',ITOA(fnGetIndex(nTest,nTest[x]))"
}

//the test case to make sure 0 gets returned if value doesn't exist in array
SEND_STRING 0, "'Index for value 4 = ',ITOA(fnGetIndex(nTest,4))"

}

}
```

And the output when button 1 is pushed:
```Line      1 :: Checking position 1 -- Index for value 1 = 1 - 18:37:21
Line      2 :: Checking position 2 -- Index for value 2 = 2 - 18:37:21
Line      3 :: Checking position 3 -- Index for value 3 = 3 - 18:37:21
Line      4 :: Checking position 4 -- Index for value 3 = 3 - 18:37:21
Line      5 :: Checking position 5 -- Index for value 2 = 2 - 18:37:21
Line      6 :: Checking position 6 -- Index for value 1 = 1 - 18:37:21
Line      7 :: Index for value 4 = 0 - 18:37:21
```

This:
```IF (nArray[x] = nValue) RETURN x
```

Is the same as this:
```IF (nArray[x] = nValue) {
RETURN x
}
```

Maybe that makes it clearer?
• X Member Posts: 4,368
Maybe looking at it this way will make it clearer. Joe's code is the better way to go about it since it's shorter and saves a few steps and accomplishes the same thing.
```DEFINE_FUNCTION INTEGER fnGetIndex(INTEGER nArray[],INTEGER nValue)

{
STACK_VAR INTEGER x ;
STACK_VAR INTEGER nIndex ;

FOR (x=1; x<=LENGTH_ARRAY(nArray); x++)
{
IF (nArray[x] = nValue)
{
nIndex = x ;
x = LENGTH_ARRAY(nArray) + 1 ;//extit loop on first match
}
}

RETURN nIndex ; //will return index of first match or 0 if no matches
}
```
• Registered User Posts: 199
I don't have my touch panel since i'm at home, but what happens

"'Index for value 4 = ',ITOA(fnGetIndex(nTest,2))"
• AMX Wizard Posts: 1,619
Why put function calls in a for loop comparator? You are calling length_array n times and it will always return the same number.
```define_function integer getArrayIndex(integer nArray[], integer nValue)
{
stack_var integer i, length
length = length_array(nArray)

for (i = 1; i <= length; i++)
{
if (nArray[i] == nValue)
{
return i
}
}
return 0
}
```
• Formerly Caffeinated Programmer Posts: 1,917
I'm not sure why, but something deep in my core tells me that you should initialize nIndex to 0 before the FOR loop. This might be a carry over from other languages or maybe I'm just paranoid

Jeff

vining wrote: »
Maybe looking at it this way will make it clearer. Joe's code is the better way to go about it since it's shorter and saves a few steps and accomplishes the same thing.
```DEFINE_FUNCTION INTEGER fnGetIndex(INTEGER nArray[],INTEGER nValue)

{
STACK_VAR INTEGER x ;
STACK_VAR INTEGER nIndex ;

FOR (x=1; x<=LENGTH_ARRAY(nArray); x++)
{
IF (nArray[x] = nValue)
{
nIndex = x ;
x = LENGTH_ARRAY(nArray) + 1 ;//extit loop on first match
}
}

RETURN nIndex ; //will return index of first match or 0 if no matches
}
```
• Original Member Posts: 562
Spire_Jeff wrote: »
I'm not sure why, but something deep in my core tells me that you should initialize nIndex to 0 before the FOR loop. This might be a carry over from other languages or maybe I'm just paranoid Jeff
"nIndex" will always be reset to zero because it is a stack_var variable.
my vote is for --> a_riot42 code:
```define_function integer getArrayIndex(integer nArray[], integer nValue)
{
stack_var integer i, length
length = length_array(nArray)

for (i = 1; i <= length; i++)
{
if (nArray[i] == nValue)
{
return i
}
}
return 0
}
```
• AMX Wizard Posts: 1,619
Spire_Jeff wrote: »
I'm not sure why, but something deep in my core tells me that you should initialize nIndex to 0 before the FOR loop.
Jeff

Don't listen to your core it is wrong. Listen to your head which is telling you the compiler has initialized your variable to 0 for you.
• Formerly Caffeinated Programmer Posts: 1,917
I am pretty sure it is something carried over from C or maybe assembly. Variables were not automatically initialized, or maybe it was they were initialized to Null (which is different than 0).

Jeff
• X Member Posts: 4,368
a_riot42 wrote:
Why put function calls in a for loop comparator? You are calling length_array n times and it will always return the same number.
```length = length_array(nArray)
```
True! Running the system function (length_array) once is better especially when dealing with large arrays.
GSLogic wrote:
"nIndex" will always be reset to zero because it is a stack_var variable.
my vote is for --> a_riot42 code:
Yep to both!
• AMX Wizard Posts: 1,619
vining wrote: »
True! Running the system function (length_array) once is better especially when dealing with large arrays.

It may not matter what the array size is. C doesn't keep track of array lengths, but Java does and I wonder if Netlinx does too. Since there is no string terminator in Netlinx I am going to guess that the length of the array is stored somewhere so calling length_array returns that stored number rather than recalculating every time. I could be wrong but that is my intuition. Still, any function call avoided is good especially if the number of times it is called depends on the input.
Paul
• X Member Posts: 4,368
a-riot42 wrote:
It may not matter what the array size is.
I just meant that on a small array putting the "length_array" system function in the for loop isn't as bad cuz it's just being called a few times but if the array is large and you have that function in the for loop it may be called on to execute thousands of times, each time returning the same result when once before the for loop would suffice. Once vs a couple or once vs a couple thousand.

a_riot42 wrote:
I am going to guess that the length of the array is stored somewhere so calling length_array returns that stored number rather than recalculating every time.
I was wondering how that worked too. Any one know how the function works? Is it just reading a stored value or what?
• AMX Wizard Posts: 1,619
vining wrote: »
a-riot42 wrote:
Once vs a couple or once vs a couple thousand.

Yes it is significant. Using Big O notation, and assuming that length_array has to count the number of indices every time, length_array runs in O(n) time. In other words, it has to do something n times, n being the size of the array. Now if you write a function that returns the index of an array, worst case it has to look at every element, again running in O(n) time. Now you are calling an O(n) function from an O(n) function so that your function now takes O(n²) comparisons for every call. A call to your function with an array of 1000 elements will make 1,000,000 comparison in the worst case.

If the length of an array is stored somewhere the length_array just does one thing regardless of the size of the input and runs in O(1) time. So now your function will run in O(n) time since your function looks at every element in the array and calls length_array n times but length_array runs in O(1) time for a total of O(n). My function, calling length_array only once and assuming the length is stored somewhere runs in O(n) time. O(n) is linear time and isn't bad so I can live with that. But 1,000,000 comparisons on an array of 1000 elements is pretty bad and gets much worse the larger the number obviously since its quadratic growth. It may not seem like a lot but O(n²) functions are sufficiently bad in most software that they simply cannot be used except in certain scientific applications that have no other way to calculate a result and it is acceptable for the computer to take hours, days or weeks to calculate a result.

If you really need it to be faster and your array is sorted like a list of increasing channel numbers or cable channels, you can find the index in O(log n) time which is very fast using a binary search technique. So for the function I wrote an array of 100 elements requires 100 comparisons O(n), but if its sorted, then a O(log n) function will make approx 6 comparisons. This gets better the bigger the array as an array with 1,000,000 elements requires a 1,000,000 comparisons but with a binary search only requires 20 comparisons. Well worth the little bit of extra code.

Faster still, but likely requiring more memory if your data has gaps is to keep the value in the element number. Then no look up is required since the index of the element 124 will be 124. That only works if you are storing integers though not some other data.
```DEFINE_FUNCTION INTEGER GetIndex(INTEGER Array[], INTEGER nValue){
STACK_VAR INTEGER x;
STACK_VAR INTEGER y;
x=1;
y=LENGTH_ARRAY(Array);
WHILE(Array[x]<>nValue and x<=y)
x++

IF(x<=y)     <---[b] you just checked if x<=y in your while guard.  Why check it again?[/b]
Return x;
ELSE
Return 0;
}
```
Paul
• Junior Member Posts: 2,159
a_riot42 wrote: »
```DEFINE_FUNCTION INTEGER GetIndex(INTEGER Array[], INTEGER nValue){
STACK_VAR INTEGER x;
STACK_VAR INTEGER y;
x=1;
y=LENGTH_ARRAY(Array);
WHILE(Array[x]<>nValue and x<=y)
x++

IF(x<=y)     <---[b] you just checked if x<=y in your while guard.  Why check it again?[/b]
Return x;
ELSE
Return 0;
}
```
The short answer is because the code needs to.

How do you know if x<=y is true or false after it drops out of the WHILE? It doesn?t matter that it was just checked since it was tested with an AND so either side or both sides could have been false and caused the fallout.

If the function doesn?t do the test and just returns the value of x then when a value is not found the function will return LENGTH_ARRAY() + 1 instead of 0.
a_riot42 wrote:
Why put function calls in a for loop comparator? You are calling length_array n times and it will always return the same number.
Yes, I?m aware of that. The example addresses the original question posed at the top of the thread and has nothing to do with the placement of LENGTH_ARRAY(). The code is testing a handful of values and I chose brevity at the expense of a few micro seconds. You chose an extra variable and an extra line of code. Jeff went with the WHILE loop instead of a FOR. Bottom line is who cares? It doesn?t make a bit of difference in this case.

If a function doesn?t work then that?s one thing and it?s probably best to point the errors out in an effort to help. But if it does work, who are we to say it?s not the right way to do it. I like to keep and open mind and enjoy reading code that uses methods that I may have never thought of before. That?s what makes programming so much fun. There is no right answer. It doesn?t matter what the vote count is. You can look at it however you want to look at it.

Here?s the way I choose to look at it:

If the code is using something like LENGTH_ARRAY(nDigitsOnOneHand)or perhaps LENGTH_ARRAY(nHundredBottlesOfBeerOnTheWall) then I?ll go with LENGTH_ARRAY() as the condition for the FOR loop and skip the extra typing.

But if the code is using something like LENGTH_ARRAY(nHugeEgo)then yes of course I?ll go with the extra code and call the function once before the FOR loop. If the array is big enough, I may even consider throwing a ?Please Wait? popup on the touch screen.
a_riot42 wrote:
Don't listen to your core it is wrong. Listen to your head which is telling you the compiler has initialized your variable to 0 for you.
You can?t count on Netlinx initializing variables to 0 automatically for you.

Consider the following:
```DEFINE_FUNCTION fnWhatever() {

INTEGER nFinger
INTEGER nFingers[4];
}
```
Netlinx will initialize nFinger to 0 but nFingers will hold garbage.

Getting back on topic?
jazzwyld wrote:
I don't have my touch panel since i'm at home, but what happens

"'Index for value 4 = ',ITOA(fnGetIndex(nTest,2))"
If you?re asking what gets RETURNed if you pass in a value of 2, the answer is 2 (the first match), not 5 (the last match). The example code and corresponding output posted demonstrates that.
• AMX Wizard Posts: 1,619
Joe Hebert wrote: »
The short answer is because the code needs to.

You are right of course, since your while guard is a compound statement. It seems like an overly complicated way to do something simple though. Whenever I see duplicate code in a function it usually points to a design flaw. Sometimes its unavoidable but in this case it certainly isn't. I don't know why you would risk using a while loop when a safer for loop accomplishes the same thing.
Joe Hebert wrote: »
Yes, I’m aware of that. The example addresses the original question posed at the top of the thread and has nothing to do with the placement of LENGTH_ARRAY(). The code is testing a handful of values and I chose brevity at the expense of a few micro seconds. You chose an extra variable and an extra line of code. Jeff went with the WHILE loop instead of a FOR. Bottom line is who cares? It doesn’t make a bit of difference in this case.

I care, and it does make a difference as I explained above. Good code is efficient code, no way around that. Calling a function that returns the same value over and over again is not brevity, its just inefficient. How can you assume there is a 'handful' of values? Because the poster only typed a few in his question? Surely you didn't expect him to type out an array of a thousand elements to ask a question about large arrays.
Joe Hebert wrote: »
If a function doesn’t work then that’s one thing and it’s probably best to point the errors out in an effort to help. But if it does work, who are we to say it’s not the right way to do it. I like to keep and open mind and enjoy reading code that uses methods that I may have never thought of before. That’s what makes programming so much fun. There is no right answer. It doesn’t matter what the vote count is. You can look at it however you want to look at it.

Just because a function works doesn't mean its well written. It has to be maintainable, easy to understand, efficient and hopefully elegant. Not sure why you would sacrifice those qualities. Just because you don't know the right way to do something doesn't mean there isn't one.
Joe Hebert wrote: »

DEFINE_FUNCTION fnWhatever() {

INTEGER nFinger
INTEGER nFingers[4];
}

To me this is just bad code and I would never write something like this. You are declaring local_var variables in a function but without explicitly using the keyword. Is this just to prove a point or do you actually write code like this?
Joe Hebert wrote: »
You can’t count on Netlinx initializing variables to 0 automatically for you.

From the Netlinx Docs:
STACK_VAR defines a non-static local variable. STACK_VAR defines local variables the same way as LOCAL_VAR, and like LOCAL_VAR, STACK_VAR can appear in any statement block. The difference is that the value stored in the variable is initialized to zero whenever the statement block is called, and the value is destroyed when the statement block is finished.
Joe Hebert wrote: »
But if the code is using something like LENGTH_ARRAY(nHugeEgo)then yes of course I’ll go with the extra code and call the function once before the FOR loop. If the array is big enough, I may even consider throwing a “Please Wait” popup on the touch screen.

If you are going to use functions that run in O(n²) time, then you will need a "Please wait..." popup. Perhaps it should say "Please wait a long time for my inefficient code to complete ..."
Joe Hebert wrote: »
Here’s the way I choose to look at it:

If the code is using something like LENGTH_ARRAY(nDigitsOnOneHand)or perhaps LENGTH_ARRAY(nHundredBottlesOfBeerOnTheWall) then I’ll go with LENGTH_ARRAY() as the condition for the FOR loop and skip the extra typing.

That just makes no sense to me at all. Why would you have two different ways of writing a function based on an assumption of the array size? To save some typing?

Paul
• Registered User Posts: 106
Let me try this again. Corrections to my original post below:

If you want to end Joe's version of the code after the first successful IF, simply add a BREAK Statement as shown below.
```DEFINE_FUNCTION INTEGER fnGetIndex(INTEGER nArray[], INTEGER nValue){

INTEGER x

x = 0
FOR (x=1; x<=LENGTH_ARRAY(nArray); x++) {
IF (nArray[x] = nValue)
{
BREAK
}
}
RETURN x

}
```
• Registered User Posts: 106
Or a more accurate block might look like this:
```DEFINE_FUNCTION INTEGER fnGetIndex(INTEGER nArray[], INTEGER nValue){

INTEGER x,idx

x = 0;
FOR (idx=1; idx<=LENGTH_ARRAY(nArray); idx++) {
IF (nArray[idx] = nValue)
{
x=idx;
BREAK;
}
}
RETURN x;

}
```

This code will run until the first nValue is found. It will then immediately save the idx in X and jump to the line after the FOR loop.
• Junior Member Posts: 2,159
DNFTT
a_riot42 wrote:
You are right of course, since your while guard is a compound statement. It seems like an overly complicated way to do something simple though. Whenever I see duplicate code in a function it usually points to a design flaw. Sometimes its unavoidable but in this case it certainly isn't. I don't know why you would risk using a while loop when a safer for loop accomplishes the same thing.
First off, I didn?t write the WHILE loop, I was simply answering your question. Second, there is no risk in the WHILE loop function that was posted. If you feel safer with FOR loops then use FOR loops.
a_riot42 wrote:
Just because you don't know the right way to do something doesn't mean there isn't one.
A trash talking programmer, how amusing. You?re right though, I?m totally inept. If you can give me your contact info I?ll consult with you first before I write a line of code and make sure it gets your approval.
```DEFINE_FUNCTION fnWhatever() {

INTEGER nFinger
INTEGER nFingers[4];
}
```
a_riot42 wrote:
You are declaring local_var variables in a function but without explicitly using the keyword. Is this just to prove a point or do you actually write code like this?
You?re insults (although not very creative) crack me up. No, those aren?t LOCAL_VARs. You?ve got it backwards. STACK_VAR is assumed. If you want a LOCAL_VAR (a variable that retains its value) you have to use the LOCAL_VAR keyword.

If your statement is based on the fact that the help file states ?If neither the LOCAL_VAR nor the STACK_VAR keyword is specified, LOCAL_VAR is assumed.? all I can say is the help file is wrong and here is code that proves it.
```DEFINE_DEVICE

dvTP = 10001:1:0

DEFINE_FUNCTION INTEGER fnVarTypeTest(){

INTEGER x
LOCAL_VAR y
STACK_VAR z

SEND_STRING 0, "'Entering fnVarTypeTest'"
SEND_STRING 0, "'Non specified x = ',ITOA(x)"
SEND_STRING 0, "'LOCAL_VAR y = ',ITOA(y)"
SEND_STRING 0, "'STACK_VAR z = ',ITOA(z)"

x++
y++
z++

}

DEFINE_EVENT

BUTTON_EVENT[dvTP,1] {

PUSH: {

fnVarTypeTest()
fnVarTypeTest()
fnVarTypeTest()
}

}
```

And the output when button 1 is pushed:
```Line      1 :: Entering fnVarTypeTest - 13:39:41
Line      2 :: Non specified x = 0 - 13:39:41
Line      3 :: LOCAL_VAR y = 9 - 13:39:41
Line      4 :: STACK_VAR z = 0 - 13:39:41

Line      5 :: Entering fnVarTypeTest - 13:39:41
Line      6 :: Non specified x = 0 - 13:39:41
Line      7 :: LOCAL_VAR y = 10 - 13:39:41
Line      8 :: STACK_VAR z = 0 - 13:39:41

Line      9 :: Entering fnVarTypeTest - 13:39:41
Line     10 :: Non specified x = 0 - 13:39:41
Line     11 :: LOCAL_VAR y = 11 - 13:39:41
Line     12 :: STACK_VAR z = 0 - 13:39:41
```

The difference is that the value stored in the variable is initialized to zero whenever the statement block is called, and the value is destroyed when the statement block is finished.
I couldn?t find that exact quote but I assume it?s there someplace. Anyway here is code that proves that statement incorrect also.
```DEFINE_DEVICE

dvTP = 10001:1:0

DEFINE_FUNCTION fnZeroTest() {

INTEGER x
INTEGER nFinger
INTEGER nFingers[4];

SEND_STRING 0, "'The value of nFinger = ',ITOA(nFinger)"

FOR (x=1; x<=4; x++) {
SEND_STRING 0, "'The value of nFingers[',ITOA(x),'] = ',ITOA(nFingers[x])"
}
}

DEFINE_EVENT

BUTTON_EVENT[dvTP,2] {

PUSH: {

fnZeroTest()
}

}
```

And here is the output when button 1 is pushed:
```Line      1 :: The value of nFinger = 0 - 14:08:09
Line      2 :: The value of nFingers[1] = 0 - 14:08:09
Line      3 :: The value of nFingers[2] = [b]33831[/b] - 14:08:09
Line      4 :: The value of nFingers[3] = [b]4352[/b] - 14:08:09
Line      5 :: The value of nFingers[4] = [b]256[/b] - 14:08:09
```

Peace Brother Paul.
• X Member Posts: 4,368
ipssheldon wrote:
If you want to end Joe's version of the code after the first successful IF, simply add a BREAK Statement as shown below.

I'm not sure which code you're looking at but in Joe's original response to the posters question he had a RETURN x after the "if" to exit upon the first match. The thread started drifting after that.
```FOR (x=1; x<=LENGTH_ARRAY(nArray); x++) {
IF (nArray[x] = nValue) RETURN x
```
• X Member Posts: 4,368
Joe Hebert wrote:
"Do Not Feed The Troll?"
```And the output when button 1 is pushed:

Code:
Line      1 :: Entering fnVarTypeTest - 13:39:41
Line      2 :: Non specified x = 0 - 13:39:41
Line      3 :: LOCAL_VAR y = 9 - 13:39:41
Line      4 :: STACK_VAR z = 0 - 13:39:41
```
So STACK_VARS will always initialize to 0 and LOCAL_VARS can hold what ever junk is left over from the previous user of that memory location similar to the interger array initialization that was discussed in the REBUILD_EVENT thread? Of course that's just an issue the first time the code runs after compiling, correct?
• AMX Wizard Posts: 1,619
vining wrote: »
So STACK_VARS will always initialize to 0 and LOCAL_VARS can hold what ever junk is left over from the previous user of that memory location similar to the interger array initialization that was discussed in the REBUILD_EVENT thread? Of course that's just an issue the first time the code runs after compiling, correct?

I wouldn't expect arrays or structures to be initialized as not many languages do that automatically, but stack_var and local_var integers get initialized to 0 as seen above. If an unspecified variables default is a stack_var rather than a local_var like the docs say, that makes more sense, but then there is a mistake in the docs or a compiler bug. But that just provides even more reason to not write ambiguous code like that.

The compiler will allow:

stack_var stackNum

or

integer stackNum

but to my thinking this creates ambiguity and looks like a mistake. I never use local_vars so I haven't come across the compiler bug/help file mistake and always explicitly determine the scope and type of my variables to avoid these types of things.
Paul
• Junior Member Posts: 2,159
a_riot42 wrote:
I wouldn't expect arrays or structures to be initialized as not many languages do that automatically
Expect the unexpected then.

Strangely enough, structure arrays, and integer arrays inside a structure array do indeed get initialized to 0 in a function as shown below. However, as shown above integer arrays alone don?t get initialized to 0 in functions. Go figure. (AFAIK all Globals do get initialized without issue.)
```DEFINE_DEVICE

dvTP = 10001:1:0

DEFINE_TYPE

STRUCT _sHand {

INTEGER Thumb
INTEGER Finger[4]

}

DEFINE_FUNCTION fnInitTest() {

_sHand sHelpingHands[2]

SEND_STRING 0, "'First hand'"

SEND_STRING 0, "'Thumb = ',ITOA(sHelpingHands[1].Thumb)"
SEND_STRING 0, "'Finger 1 = ',ITOA(sHelpingHands[1].Finger[1])"
SEND_STRING 0, "'Finger 2 = ',ITOA(sHelpingHands[1].Finger[2])"
SEND_STRING 0, "'Finger 3 = ',ITOA(sHelpingHands[1].Finger[3])"
SEND_STRING 0, "'Finger 4 = ',ITOA(sHelpingHands[1].Finger[4])"

SEND_STRING 0, "'Second hand'"

SEND_STRING 0, "'Thumb = ',ITOA(sHelpingHands[2].Thumb)"
SEND_STRING 0, "'Finger 1 = ',ITOA(sHelpingHands[2].Finger[1])"
SEND_STRING 0, "'Finger 2 = ',ITOA(sHelpingHands[2].Finger[2])"
SEND_STRING 0, "'Finger 3 = ',ITOA(sHelpingHands[2].Finger[3])"
SEND_STRING 0, "'Finger 4 = ',ITOA(sHelpingHands[2].Finger[4])"

}

DEFINE_EVENT

BUTTON_EVENT[dvTP,1] {

PUSH: {

fnInitTest()
}

}
```

Output when button 1 is pushed:
```Line      1 :: First hand - 20:41:39
Line      2 :: Thumb = 0 - 20:41:39
Line      3 :: Finger 1 = 0 - 20:41:39
Line      4 :: Finger 2 = 0 - 20:41:39
Line      5 :: Finger 3 = 0 - 20:41:39
Line      6 :: Finger 4 = 0 - 20:41:39
Line      7 :: Second hand - 20:41:39
Line      8 :: Thumb = 0 - 20:41:39
Line      9 :: Finger 1 = 0 - 20:41:39
Line     10 :: Finger 2 = 0 - 20:41:39
Line     11 :: Finger 3 = 0 - 20:41:39
Line     12 :: Finger 4 = 0 - 20:41:39
```