When call func1(p, q) it similar x=p and y=q then the function work on x and y without changing p and q in main() function.
When call func2(p, q) it similar that only y=q and function work on p and y any change happens to y does not change q but p are used than any change happens inside the function will happen in main().
Every variable is a memory location, which has its address defined.
That address can be accessed using the ampersand (&) operator (also called the address-of operator), which denotes an address in memory.
Address-of : operator (&): returns the memory address of its operand.
&x it mean : the address in memory that hold the value of variable x of type integer.
When passing by value in a function (use x), it does not change the value of the variable, but rather makes a copy of the value and does its job. As for passing by reference (use &x), it does not make a copy of the variable, but rather uses the variable itself, and any change inside the function will change its value.
x%y it mean just the reminder of the division x/y.
in this case it return x-- when the reminder == 0. and return y++ when the reminder != 0.
When you call the function func(p, q) you passing by reference p, and passing by value q.
The function store the value of q in new adress (adress of y) any changes happens to y does not affect p, but it store the value of p in the same adress (adress of x same adress of q), and any changes happend to x affect q.
See this code you will see the changes.
you will see when we call func1 (pass by value) that x and y take the value of p and q then the value of x and y change without changing rhe value of p and q.
in the second case you will see when we call func2 (pass by reference) that x take the value of p then the value of x change and even value of p change too.