C series for 1st sem students: Pointers in function calls

Posted on Posted in Blogs, Technology





C is a procedural language, which means it follows a series of steps/procedures in a systematic order to solve a problem. These procedures are often organized in functions. These functions take in some value(s) as argument(s), operate on them and return an output. But apart from this approach, a function can even change the state of other variables in the global scope, perform input/output operations etc. This is called side effects of a function. Though it is not recommended in declarative/functional programming, this approach has its benefits in C.

Conventionally, when a variable is passed into a function, its value is copied into a local variable. The operations within the function are then done on this local variable. Thus the original variable doesn’t change its value after the function is executed. This prevents the above mentioned “side-effect” of the function. This way of passing arguments in a function is called “pass by value”. Let’s see an example.

In the shown example, we create a function swap to exchange the values of two variables. We create a temporary variable temp to hold the first variable’s value, then copy the value of the second variable into the first and then copy the value held in the temporary variable into the second variable.

In the main function we declare the two variables we want to swap and pass them into the function swap on line 21. Then we print the values to check if they actually got swapped.

But as you see in the output of the integrated terminal, the values didn’t get swapped. This is because conventionally C avoids function side effects by coping the values of the arguments into local variables (here variables first & second). The operations within the function are executed upon these variables rather than those passed as arguments. So the original variables retain their values even after execution of the function. We can check this by printing the local variables within the swap function.

 

 

 

 

As we can see in line 14 & 15, we print the local variables after swapping them, and in the output it is verified that they are swapped successfully.

 

To get around this problem, we can use pointers to actually pass the variables, rather than only their values, into functions. This is done by passing a reference to the variables as arguments; so this method is called “pass by reference”. This is a cool hack because fundamentally the way in which functions work doesn’t change. A function will always copy the value of passed arguments into temporary variables, but when the arguments are addresses to some memory locations (pointers), the operations within the function can change the values residing in those memory locations. So while passing pointers in a function, the values of these pointers are copied into temporary (local) pointers, i.e. pass by value is employed, but the variables that they point to are still pointed by the local pointers within the function. So we can change their values within the function. Let’s write the same swap function by using pointers as arguments.

In the shown program, we create pointer variables p1 & p2 in lines 15 & 16 respectively. They point to the address of a & b respectively. We pass them in the swap function. In order to accommodate them, we slightly modify the swap function. We change the parameters to be pointers of int type. Within the function, we first create a temporary integer variable, and pass the value of the variable pointed by the first pointer into it. The first pointer points to the variable a, which has the value of 10. So temp now has the value 10.

Then we pass the value of the variable pointed by the second pointer, into the variable pointed by the first pointer. The second pointer points to b which has 20 in it. So 20 is copied into a because the first pointer points to variable a. Thus we successfully changed the value of a variable inside a function i.e. we implemented a side-effect in this function. Now a = 20!!!

Then we copy the value of the temporary integer variable temp into the variable pointed by the second local pointer, i.e. into b. Thus b = 10. So we successfully swapped the values of two variables by passing their reference into a function. This is verified in the terminal output.

In using pointers, we are often confused by the syntax. Remember these points.

  1. While declaring we use asterisk as int *p1 or int* p1. Both are same, a pointer of type int is created. Let’s assume an integer variable a = 10.
  2. While assigning value to a pointer we use ampersand as p1 = &a or int* p1 = &a or int *p1 = &a. &a means the address of a. Remember, here *p1 is not same as p1, *p1 = &a is invalid code!!!
  3. *p1 gives the value stored inside the variable it points to. So *p1 = 10.
  4. p1 gives the address of the variable it points to, i.e. the address of a. So p1 = &a.
  5. &p1 gives the address of itself.

Thus the syntax *p1 is a value and p1 is an address. Most errors occur when we mistakenly assign an address to an integer variable or a value into a pointer (which expects an address). In the above program, in line 19, swap(*p1,*p2) will give an error since *p1 is a value whereas the function expects an address. Similarly in line 6, temp = first will give an error since temp is an integer but first gives an address. Now go through the program again, and much of the confusion will be cleared.

If you are still confused, please comment below and I’ll try to clear your doubts.

You can download the code { here }





If you liked this article please comment and show your support and interest so that I’ll be motivated to continue this effort. Like our facebook page if you haven’t already. And if you have any questions please comment. I’ll try to reply all.

Comments

comments