PS Function can modify multiple variables using struct(ure) type of variable.
You can also pass an array into a function and alter their values. The power of C and C++, however, is the ability to use pointers when you need the function to change several values and give them back to you. The Bucket Analogy makes it easy to understand pointers. I'm going to take a few liberties along the way, but hopefully you'll see what a pointer is when we're done.
Defining a variable like:
int val;
creates a bucket named val and places that bucket somewhere in memory (usually SRAM). Let's say it ends up at memory address 1000. That memory address is often referred to as the lvalue of val. That is, the lvalue of a variable is where that variable "lives" in memory. Because val is an int, the size of the bucket is such that it can hold 2 bytes of information. When you look inside the bucket, you can see whatever numeric value has been assigned to val. This value is called the rvalue of val. Depending upon the point in the program where val is defined, it probably contains an rvalue that is some random bit pattern that just happened to exist at its lvalue (memory addresses 1000 and 1001).
The statement:
val = 10;
assigns the value 10 into val. Stated differently: a 2-byte binary representation of 10 is transferred to the lvalue of val. This means the rvalue of val is now 10. Now consider:
int val;
val = 10;
myFunction(val); // This is the "function call to myFunction()"
Serial.println(val);
// Probably a bunch of lines of code here...
void myFunction(int n) {
n = n * 10;
}
The function call to myFunction() causes code to go to val's lvalue, peek inside and see the rvalue of 10, and copy that value (i.e., the rvalue of val) into a 2-byte temporary variable stored in a chunk of memory called the stack. Let's pretend the stack is at memory address 2000. When program control gets "into" myFunction(), it sees that there is a temporary variable named n sitting on the stack at memory address 2000. Code then multiplies that 2-byte value by 10, and places it back at memory address 2000. Program control returns back to the Serial.println() method call to display the value of val and the program display the value 10. The reason is because the work done in myFuncion() was done on a copy of val, not val itself.
But what it you want the function to actually change val? Lets make three changes to our program:
myFunction(&val); // This is the "function call to myFunction()"
Serial.println(val);
// Probably a bunch of lines of code here...
void myFunction(int *n) {
*n = *n * 10;
Note the ampersand (&) in front of val in the function call to myFunction(). All the amperand says is: Hey! Treat me differently. Don't send a copy of my rvalue, send my lvalue instead. This means that the value 1000 is sent to the function, not 10. Because we are passing the address of where val lives in memory to myFunction(), we need to tell it that it is receiving an lvalue (i.e., memory address) rather than a copy of the rvalue of some data. That's what the asterisk tells the myFunction() code in the expression "int *n" in the function's parameter list. Most programmers say "n is a pointer to an integer value" because its a lvalue, not an rvalue.
To use the pointer in an expression like:
*n = *n * 10;
The asterisk causes code to be generated that goes to the lvalue is was given (i.e., 1000), fetch the 2 bytes found there (it knows it needs 2 bytes because of the int type specifier for the pointer n), which means it has the value 10, and then it multiplies that ravalue by 10 to get 100. However, the *n on the left side of the assignment says to go to memory address 1000 and place the new value of 100 into the 2 byte bucket found at that memory address. Control returns back to the Serial.println() method call.
However, now when Serial.println() fetches the value of val, it is 100 because it was permanently changed via the use of pointers in the myFunction() code. The processes of using a pointer to alter data is called indirection.
Now, if you wanted to have a function "return two values" which is impossible in C, could you instead pass the lvalues of those two variables to your function and use indirection in the function to permanently change those value? Think about it.