Jump to content
sarogahtyp

[SOLVED] How to get pointers and copies of arrays

Recommended Posts

Hey guys

in another topic it came to the question how pointers are handled in sqf.

I know them from C and I know they are sometimes essential if u want to write fast code.

The question is, how can I get a pointer of an array and how can I return it from and pass it to functions and how can I do the same with a complete copy of an array?

Share this post


Link to post
Share on other sites

To get pointer:

_array1 = [1,2,3];
_array2 = _array1;

_array2 now points to _array1. changes made to either of the arrays applies to both arrays.

 

To get copy:

_arrayCopy = + _array1;

_arrayCopy now has copy of _array1 contents.

 

 

I don't know how pointers work in sqf when returning from function, I assume the same way.

  • Like 1

Share this post


Link to post
Share on other sites

okay I should have read this better :-)

 

just for reference (these are thoughts only. I ve tested nothing of it):

 

pass pointer:

_array = [0,1,2];

[_array] call any_function; 

//this can be bad if spawn is used instead of call because if the main function is finished then the local _array should be destroyed and the passed pointer will then point nowhere.
 

pass a copy:

_array = [0,1,2];

[+_array] call any_function; 
 

return pointer:

any_fnc =

{
 _array = [0,1,2];

 _array
};
// this should not work with a local array because it should be destroyed after any_fnc is finished... but syntax should be fine:-)
return copy:

any_fnc =

{
 _array = [0,1,2];

 +_array
};
EDIT:

As gc8 said below I could be wrong with my comments in these snippets...

Edited by sarogahtyp
  • Like 1

Share this post


Link to post
Share on other sites

 

 

_array = [0,1,2];

[_array] call any_function;

//this can be bad if spawn is used instead of call because if the main function is finished then the local _array should be destroyed and the passed pointer will then point nowhere.

 

have you tested it? I was thinking that maybe sqf uses shared pointer system so that the array would be valid at any time inside the function.

  • Like 1

Share this post


Link to post
Share on other sites

have you tested it? I was thinking that maybe sqf uses shared pointer system so that the array would be valid at any time inside the function.

I should ve written it. I tested nothing of it. these r thoughts only. I will update the post above with that information.

Share this post


Link to post
Share on other sites

ok I tested with this:

 

_array = [1,2,3];


TestFn = 
{
_a = _this select 0;

sleep 1;

hint format["_a = %1",_a]; // prints _a = [1,2,3]
};


[_array] spawn TestFn;

so it seems to work even the initial _array goes out of scope.

Share this post


Link to post
Share on other sites

idk if we talk bout the same. I meant something like this:

 TestFn = 
 {
  _a = _this select 0;

  sleep 1;

  hint format["_a = %1",_a]; // prints _a = [1,2,3]
 };


 OuterFn =
{
 _array = [1,2,3];

 [_array] spawn TestFn;
};

call OuterFn; 

Share this post


Link to post
Share on other sites

idk if we talk bout the same. I meant something like this:

 

 TestFn = 
 {
  _a = _this select 0;

  sleep 1;

  hint format["_a = %1",_a]; // prints _a = [1,2,3]
 };


 OuterFn =
{
 _array = [1,2,3];

 [_array] spawn TestFn;
};

call OuterFn; 

 

that still prints "_a = [1,2,3]" 

  • Like 1

Share this post


Link to post
Share on other sites

To get copy:

_arrayCopy = + _array1;

_arrayCopy now has copy of _array1 contents.

I'd a bit extend, if you don't mind:

 

To get a deep copy: 

_arrayCopy = + _array1;

To get a shallow copy:

_arrayCopy = [] + _array1;

Example:

_a = ["foo", "bar"];
_b = ["baz", "qux"];
_c = [_a, _b];
_d = +_c; // _d is no longer related to _a or _b
_e = []+_c; // does not copy _a and _b, but copies pointers to their data
_d select 0 set [0, "nobody expects"];
// _a is still ["foo", "bar"]; _d is [["nobody expects", "bar"], ["baz", "qux"]]
_e select 0 set [0, "spanish inquisition"];
// _a is ["spanish inquisition", "bar"]; _d is [["nobody expects", "bar"], ["baz", "qux"]]; _e is [["spanish inquisition", "bar"], ["baz", "qux"]]

In general, every time (incl. passing args to and returning from functions) you deal with array you deal with pointer to it only, unless you have explicit deep copying. Therefore if function creates copy of array it should inform user of it. Otherwise is very bad taste.


UPD.

I was thinking that maybe sqf uses shared pointer system so that the array would be valid at any time inside the function.

Exactly. Therefore array exists while at least one variable (i.e. name in script) points to its data.

You return from function, local pointer (not array) expires, external continues to hold that data.

  • Like 2

Share this post


Link to post
Share on other sites

Alright, I haven't tested this, but thinking through the following script, I am pretty sure this is how it works.

_variable1 = 5;
_variable2 = _variable1;

//_variable2 is now a copy of _variable1.  Any change to either will have no effect on the other.

_variable1 = "hello world";
hint str _variable2; //will display the number 5.

//Arrays are a little different.

_array1 = [[1,2,3],[4,5,6]];
_array2 = _array1;

//_array2 and _array1 are both pointers to the array.  Any change made to either _array1 or _array2 will be reflected by both variables.

_array1 pushBack [7,8,9];
hint str _array1;  //will obviously display [[1,2,3],[4,5,6],[7,8,9]]
sleep 5;
hint str _array2; //will also display [[1,2,3],[4,5,6],[7,8,9]]

//we can also maintain pointers to the same array in different scripts, and therefore manipulate data in one script from another script.

_array1 spawn {
  _array3 = _this;
  _array3 set [0,"Tom"];
  _array3 set [1,"Dick"];
  _array3 set [2,"Harry"];
};

sleep 5;
hint str _array2;  //will display ["Tom","Dick","Harry"]

//what happens if we start changing the variables?  

_array2 = "sausages";
sleep 5;
hint str _array1; //will hint ["Tom","Dick","Harry"]
sleep5;
hint str _array2; //will hint sausages.

//So the array still exists out there, but _array2 no longer points to it.  How can we destroy the array?

_array1 = nil;

//The array ["Tom","Dick","Harry"] is now gone and no longer in memory.
//The array is not destroyed because we set the pointer _array1 to nil.
//The array is destroyed because there are no more pointers that point to it.

//What about other methods of getting and setting variables?

myGlobalVariable = ["cheese","burger"];

//Now we have a global variable that points to ["cheese","burger"]
//Lets see what happens if we start passing this global variable around all over the place.

_myVar1 = missionNamespace getVariable "myGlobalVariable";
_myVar2 = myGlobalVariable;

sleep 5;

_myVar1 pushBack "with";
hint str myGlobalVariable; //will display ["cheese","burger","with"]

sleep 5;

_myVar2 pushBack "pickles";
hint str myGlobalVariable;  //will display ["cheese","burger","with","pickles"]

_myVar2 spawn {
  _this set [3,"tomatoes"];
};

sleep 5;

hint str myGlobalVariable; //will display ["cheese","burger","with","tomatoes"]

missionNamespace setVariable ["myGlobalVariable",["communism","capitalism"]];

//myGlobalVariable should now point to a different array, in this case, ["communism","capitalism"]

hint str myGlobalVariable; //will display ["communism","capitalism"]

//however, our array ["cheese","burger","with","tomatoes"] is not gone, it still exists in memory because we have some local variables pointing to it
//this is important to note.  _myVar1 and _myVar2 do not point to the myGlobalVariable pointer, they instead point directly to the original array.
//setting the myGlobalVariable pointer to point at a new array does not redirect variables that were defined with _varName = myGlobalVariable

sleep 5;
hint str _myVar1;  //will display ["cheese","burger","with","tomatoes"];

//but what if we want changes in an array done to an array to be unique to that variable and not reflected in all other variables pointing to the same array?
//We make a copy of the array

_myVar2 = + _myVar1;
_myVar2 deleteAt 0;
hint str _myVar1; //will display ["cheese","burger","with","tomatoes"]
sleep 5;
hint str _myVar2;  //will display ["burger","with","tomatoes"]

//note that using + makes a deep copy.  Lets examine what that means using some new arrays.  First we will redefine our old variables.

_myVar1 = [["ham","burger"],["hot","dog"]];
_myVar2 = + _myVar1;

_mySubArray = _myVar2 select 0;
_mySubArray set [0,"tofu"];

hint str _myVar1; //will display [["ham","burger"],["hot","dog"]]

sleep 5;

hint str _myVar2; //will display [["tofu","burger"],["hot","dog"]]


  • Like 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×