Think carefully for a moment about what is happening in these fragments
of code. The variables num1 and num2 in main are
ordinary integers, so when main prefixes them with ampersands
(&) while passing them to get_values, it is really passing
integer pointers. Remember, &num1 should be read as "the
address of the variable num1".
The code reads like this:
get_values (&num1, &num2);
"Evaluate the function get_values, passing to it the
addresses at which the variables num1 and num2 are stored.".
The function get_values is defined like this:
void get_values (int *num_ptr1, int *num_ptr2)
"Define the function get_values. It returns a void
value (so it operates only via "side effects" on the variable
parameters it is passed). It takes two parameters, both of type
int *. The first parameter is called num_ptr1 and is a
pointer to an integer value, and the second parameter is called
num_ptr2 and is also a pointer to an integer value. When this
function is called, it must be passed the addresses of variables, not the
variables themselves."
Remember that declaring a variable with an asterisk (*) before it
means "declare this variable to be a pointer", so the formal
parameters of get_values are integer pointers. The parameters
must be declared this way, because the main function sends
the addresses of num1 and num2 -- that is, by the time
the get_values function receives the parameters, they are
already pointers -- hence their names in get_values:
num_ptr1 and num_ptr2, rather than num1 and
num2.
In effect, we are "matching up" the data types of num1 and
num2 with those of num_ptr1 and num_ptr2,
respectively, when we prefix num1 and num2 with ampersands
while passing them, and prefix num_ptr1 and num_ptr2 with
asterisks in the parameter list of the function get_values. We do
not have to write num_ptr1 = &num1; and num_ptr2 = &num2;
-- the calling convention does that for us.
Important! This is a general rule in C: when you pass actual
parameters as pointers using ampersands (e.g. &num1, "the
address of the variable num1"), you must use asterisks to
declare as pointers the corresponding formal parameters in the function
to which you pass them, (e.g. int *num_ptr1, "the contents of
the location pointed to by num_ptr1").