Dear friends,
I feel like a "dumb". After years of experience in other languages, I find it very difficult to understand some details on how pointers and structs work in lite-C/Zorro. If there is some good soul giving some help I will be very thankful.

Sorry if this is long, but it is three different experiments.

The reason of all is that I would like to return "multiple values" from a function, and possibly across files. Being this "impossible" as usual, the idea "was" to change some variable by reference, letting then the main function use the values changed within the function.

1. I start from the manual, and try to go from simple to more difficult.

This is the example from the manual, with just an output generated to see what the values are:


Code:
function change_variable(var myvar)
{
  myvar += 1;
}


function change_variable_p(var *myvar)
{
  *myvar += 1;
}
void main() {
	var x = 10;
	change_variable(x);   // now x is still 10
	printf(strf("First function. x = %0.f", x));
	change_variable_p(&x); // now x is 11
	printf(strf("\n\nSecond function. Now x = %0.f", x));
	
}



And in fact the output is correct:
Code:
testPointerMain compiling..........
First function. x = 10

Second function. Now x = 11



And here the first problem. At this time, the manual says:
Quote:
Lite-C automatically detects if a function expects a variable or a pointer to a variable, so you can usually omit the '&' and just write:

change_variable_p(x);


I make exactly this, i.e. remove the reference "&" from the call to change_variable_p, and the output now is (Zorro 1.50):

Code:
testPointerMain compiling.......
Error in 'line 53: 

change_variable_p(): Pointer expected
<change_variable_p(x); // now x is 11>.



mmm... blush What's up here?

OK: let's live with the fact that "&" is needed, in spite of the manual...

2. Now, the game studio manual has another nice example. This works with arrays, which is actually what the whole should be particularly good for.

They propose this example:

Code:
function vector_add2(var* sum,var* v1,var* v2)
{ // calculate the sum of two vectors
   sum[0] = v1[0] + v2[0];
   sum[1] = v1[1] + v2[1];
   sum[2] = v1[2] + v2[2];
} 	

void main() {
	var vector1[3] = { 1,2,3 };
	var vector2[3] = { 4,5,6 };
	var vector3[3];
	
	vector_add2(vector3,vector1,vector2); // vector3 now contains 5,7,9
	printf("vector3[0] = %0.f, vector3[1] = %0.f, vector3[2] = %0.f", 
	        vector3[0], vector3[1], vector3[2]);
}



And in fact the nice output is:

Code:
testPointerMain compiling..........
vector3[0] = 5, vector3[1] = 7, vector3[2] = 9



Now, here the syntax seems pretty similar to C/C++. You pass the vector_add2 function three parameters, which are correctly understood as pointers to vectors. Within the function, you have not to specify further that you're working with
pointers, the function returns nothing, but just changes vector3 in place, and it is perfectly available to the main function after the call. Wonderful and: as expected!!!

A note is that GameStudio's manual also specifies that to declare a pointer you append the * symbol to the type of the variable. If I don't remember it wrong, in C int* a and int *a are in such cases identical. And in C-lite too: if we change the definition of the function in

Code:
function vector_add2(var *sum,var *v1,var *v2)



the result does not change. Wonderful and as expected!

Now, let's try to make it even simpler. A pointer should be a pointer, either that it points to an array or to a variable:

Code:
function getSomething(var* target) {
	target = 5;
}

void main() {
	var got_it;
	getSomething(got_it);
	printf("I have got it: %0.f", got_it);
}



This doesn't compile, and the only way of having it working is to repeat the construct of number 1:

Code:
function getSomething(var* target) {
	*target = 5;
}

void main() {
	var got_it;
	getSomething(&got_it);
	printf("I have got it: %0.f", got_it);
}



...thus passing the reference and using the pointer within the function... Why??? Why does a pointer to an array work "the normal way" and a pointer to a var, or to an int or to something else require a different syntax?

3. Structs...

Now let's see with structs.
The manual says:

Quote:
In standard C / C++, members of structs are accessed by a dot '.' and members of struct pointers are accessed by an arrow '->'. In lite-C, the dot '.' can normally be used for both because the compiler automatically detects whether a simple object is a pointer or not. You only need to give the '->' in ambiguous cases, for instance when the struct pointer is a member of another struct pointer.


Now let's see the working version of the script (found out by chance by changing things one after the other):

Code:
typedef struct {
	int a;
	int b;
	int c;
} one_str;

function getStruct(one_str* target) {
	target->a = 1;
	target->b = 2;
	target->c = 3;
}

void main() {
	one_str my_values;
	
	getStruct(&my_values);
	printf("my_values.a = %i, my_values.b = %i, my_values.c = %i", 
				my_values.a, my_values.b, my_values.c);
}



The output is, as it should:
Code:
testPointer2 compiling...........
my_values.a = 1, my_values.b = 2, my_values.c = 3



Now, anyway let's note something.

  • In the getStruct function, once we declare the type of the argument as a pointer, we are no longer requested to use the pointer when assigning values (good! But different from an integer variable, for instance).
  • As soon as we take the manual for granted, whe should be able to change -> with simple dot. I.e.


Code:
target.a = 1;
target.b = 2;
target.c = 3;


In fact the *target pointer should not be a member of another struct pointer...
But the message from the Zorro compiler is amazing:
Code:
testPointer2 compiling.......
Error in 'line 46: 
'a' : Pointer expected
< 	target.a = 1; >.


OK, lesson learned. It looks like the dot notation for accessing members of structs is no good in lite-C.
So I replace in the function the dots with the ->, as they were before, and, as I would like to have a common and easy to remember syntax, I then decide to replace the dot notation with the -> also in the main:

Code:
void main() {
	one_str my_values;
	
	getStruct(&my_values);
	printf("my_values.a = %i, my_values.b = %i, my_values.c = %i", 
				my_values->a, my_values->b, my_values->c);
}



And this is now the nice message of the Zorro compiler:

Code:
testPointer2 compiling......
Error in 'line 56: 
'a' : is not a member of ''
<my_values->a, my_values->b, my_values->c);>.



Conclusion: in the function we must use -> and in the main we must use dots... why why why???? And: in passing the my_value struct to the function, we must forcedly use the &, in spite of the getStruct function already knowing that it is supposed to be a pointer, differently from vectors and similar to "atomic variables". Again...

crazy Please please please... Is there someone able to give some explanation here? Finding out things by trial and error is always useful... But it is also a bit time consuming and, in the absence of a "clear rule", it is likely that the trial and error will come up again and again in the future...


Thank you so much in advance!

fs