How2Lab Logo
tech guide & how tos..


Pointers in C - Part 7 of 9


We already know that C follows call by value scheme for parameter transfer in a function call. Thus when a pointer is passed as a parameter to a function, it effectively implements call by reference. We have already mentioned in one of the earlier articles on C that in the call by value scheme, the data items passed as actual parameters get copied to the corresponding formal parameters of the called function. Thus any changes made to the content of those variables are not carried back to the calling function. But if a parameter is passed by reference (i.e. address of the variable or pointer to the variable is passed), the content of that address can be accessed freely in either of the calling and called functions to the extent that changes made in any function gets reflected in the other.

For example, in the code below, if a variable x in the calling function f1() is declared as a pointer, and x is passed to the called function f2(), any operation that you do in f2() with pointer v will effectively be the same as any operation you do with x in f1().

f1()
{
	vector *x; 
	f2(x); 
}

f2(vector *v)
{
	...
}

In the above example, using the call be value scheme the l-value of x is passed to v, thereby making v point to the same memory space that x is pointing to. And hence, v and x are two pointers pointing to the same memory space. It is because of this property of pointer variables and the arithmetic operations allowed on them that C does not need an explicit call by reference scheme of parameter transfer. The call by value scheme of parameter transmission is sufficient.


Below is another example to illustrate how pointers can be passed to a function. In this example the function f1() resets the r-values of variables u and v.

#include <stdio.h> 
main()
{
	int u=1, v=3; 
	void f1(int *pu, int *pv); 
	...
	f1(&u, &v);
}

void f1(int *pu, int *pv) 
{
	*pu = 0;
	*pu = 0;
	return; 
}

We have already been seeing the usage of passing pointer to a function in the standard library function scanf(), which accepts the address of a variable for inputting data into the variable. Let us look at a variation of the scanf function using pointers:

void f1(int *pu, int *pv) 
{
	int *pu, *pv;
	pu = &u;
	pv = &v;
	scanf("%d %d", pu, pv); //Note that no & symbol appears before pu and pv
	...
}

Let us look at a few more examples to strengthen our understanding of parameter transfer of pointers.

Consider a function change given below. In the second function f1() when we call change, instead of passing simple variables and constants, notice that we are passing components of an array data structure, viz. the r-value of second element and the l-value of third element of array c.

/* Called function */
void change(int i, int *j)
{
	i = i + 5;
	*j = *j + 5;
	printf("i = %d, j = %d\n", i, *j);
	return;
}

/* Calling function */
void f1()
{
	int c[4];
	int m;
	c[0] = 5;
	c[1] = 6;
	c[2] = 7;
	c[3] = 8;

	change(c[1], &c[2]);

	for(m=1; m <= 3; m++)
		printf("%d\t", c[m]);
	printf("\n");
}

When f1() is executed, the values printed are:

i = 11, j = 12
6  12  8

Here the first parameter c[1] is transmitted by value. Hence the expression c[1] is evaluated by referencing array c and then selecting its second component. The result is the r-value of that component. Formal parameter i of function change() is initialized with this r-value.

The second parameter &c[2] is evaluated and a pointer to the third element of c is passed. Assignment within function change() then directly references and changes the value stored in the element c[2] via the pointer stored in the formal parameter j of change().


Now let us look at another function newChange() having parameters which are both pointers to integers:

void newChange(int *i, int *j)
{
	*i = *i + 1;
	*j = *j + 1;
	printf("%d %d\n", *i, *j);
}

void f1()
{
	int c[4];
	int m;
	c[0] = 5;
	c[1] = 6;
	c[2] = 8;
	c[3] = 9;

	m = 1;
	newChange(&m, &c[m]);

	for(m=1; m <= 3; m++)
		printf("%d\t", c[m]);
	printf("\n");
}

As you can see, the function f1() is quite the same as the previous example. However, it is now calling function newChange(). What values would be printed when function f1() is executed now?

Note that m has an initial value 1. However, due to passing &m, *i in newChange() changes the value of m to 2 when the statement *i = *i + 1; is executed. Thereafter when the statement *j = *j + 1; is executed, since j points to &c[1] (not &c[2]), this statement changes the value of c[1] to 7.

Thus the output the above code will be: 2 7 7 8 9.

Here it is important to note that when newChange() is called with the second parameter &c[m], the value of m at that point is 1 and hence address of c[1] gets passed and pointed to by j. Hence, changing the value of m in the statement *i = *i + 1; does not impact j.



Function returning pointer

The return value of a function can also be a pointer to a function. For instance, in the example below, the called function compress() returns a pointer to the calling function main(). Though this may not be a very meaningful illustration as you may ask, why return s when it is already available in main(), this is just to demonstrate that a pointer can be returned by a function.

/* Program to remove multiple consecutive occurrence of the same character in a string */
#include <stdio.h>
main()
{ 
	char string[81], *out;
	char *compress(char s[]);

	printf("\nEnter a String: "); 
	gets(string); fflush(stdin);

	out = compress(string);
	printf("\nOutput String is: %s\n", out); 
}

/* function returns a pointer of type character */ 
char *compress(char s[])
{
	char *q, *r;
	r = s;
	q = s;
	while(*r)
	{
		for(; *q == *r; r++);
		q++;
		*q = *r;
	}
	return s; //returns pointer to the passed string
}

Here is a summary of the different types of pointer declarations, with increasing order of complexity:

int *p;                 /* p is an pointer to an integer data */

int *p[15];             /* p is an array of 15 pointers to integer data */

int (*p)[15];           /* p is a pointer to a 15-element integer array */

int *p(int)             /* p is a function with integer argument and returns a 
                           pointer to an integer */

int *p(int *x)          /* p is a function with integer argument which is a pointer      
                           to an integer data, and p returns a pointer to an integer */

int (*p)(float *x);     /* p is a pointer to a function which has an argument that  
                           is a pointer to a floating point data, and the function     
                           returns an integer data */

int *(*p[10])(float a);  /* p is an array of 10 pointers to function. Each pointer
                            accepts a floating point data as argument. p returns a
                            pointer to integer data */

Share:
Buy Domain & Hosting from a trusted company
Web Services Worldwide | Hostinger
About the Author
Rajeev Kumar
CEO, Computer Solutions
Jamshedpur, India

Rajeev Kumar is the primary author of How2Lab. He is a B.Tech. from IIT Kanpur with several years of experience in IT education and Software development. He has taught a wide spectrum of people including fresh young talents, students of premier engineering colleges & management institutes, and IT professionals.

Rajeev has founded Computer Solutions & Web Services Worldwide. He has hands-on experience of building variety of websites and business applications, that include - SaaS based erp & e-commerce systems, and cloud deployed operations management software for health-care, manufacturing and other industries.


Refer a friendSitemapDisclaimerPrivacy
Copyright © How2Lab.com. All rights reserved.