How2Lab Logo
tech guide & how tos..


Functions in C - Part 5 of 5


Explicitly transmitted parameters and results are the major alternative approaches for sharing data objects among functions. In the receiving function, each data object is given a new local name through which it is referenced. The arguments of a function may be obtained both through parameters and through nonlocal references (and less commonly, through external files). Similarly the results of a function may be returned through parameters through assignments to nonlocal variables, (or files), or through explicit function values. Thus the terms argument and result apply to data sent to and returned from functions through a variety of language constructs. In narrowing our focus to parameters and parameter transmission, the terms actual parameter and formal parameter become central.

Let us look at the following program:

 #include <stdio.h>

 int max(int x, int y)
 {
	int max_num = 0;
	...
	return(max_num);
 }

 main()
 {
	/* automatic or local variables */
	int max_val;
	int a = 20, b = 30;
	max_val = max(a, b);
	printf("Max = %d\n", max_val);
 }

In the above program, the calling function main calls function max and passes actual parameters a & b to it. The called function max accepts the passed actual parameters in its formal parameters x & y respectively.

A formal parameter is a type of local data object within a function. The function definition normally lists the names and declarations for formal parameters as part of the specification. A formal parameter name is a simple identifier, and the declaration ordinarily gives the type and other attributes, as in the case of an automatic local variable declaration. For instance, in the above example program, int max(int x, int y) defines two formal parameters named x and y and declares the type of each. The declaration of a formal parameter, however, does not mean the same thing as a declaration for a variable. The formal parameter, depending upon the parameter transmission mechanism to be discussed shortly may be an alias to the actual parameter data object. It may simply contain a copy of the value of those data objects.

An actual parameter is a data object that is shared with the calling function. An actual parameter may be a local data object belonging to the calling function. It may be a formal parameter of the calling function or it may be a non-local data object visible to the called function. It may be a result returned by a function invoked by the calling function and immediately transmitted to the called function. An actual parameter is represented at the point of call of the function by an expression, termed an actual parameter expression that ordinarily has the same form as any other expression in the C language.

When a function is called with an actual parameter expression, the expression is evaluated at the time of the call, before the function is entered. The data objects that result from the evaluation of the actual parameter expressions then become the actual parameters transmitted to the called function.


Establishing the Correspondence

When a function is called with a list of actual parameters, a correspondence is established between the actual parameters and the formal parameters. The correspondence is established by pairing actual and formal parameters based on their respective positions in the actual and formal parameter lists. The first actual and first formal parameters are paired, then the second in each list, and so on. For instance the function main calls the function max with actual parameter a and b. Since x and y are formal parameters of max, a is associated with x and y with b.


Methods for Transmitting Parameters

Call by name

This scheme of parameter transmission views a call as a substitution for the entire body of the subprogram. Thus each formal parameter stands for the actual evaluation of the particular actual parameter. Each reference to a formal parameter requires a re-evaluation of the corresponding actual parameter.

Therefore, at the point of call of the subprogram, no evaluation of the actual parameters is done until they are actually referenced in the called function. The parameters are transmitted unevaluated, and the called function determines when, if ever, they are to be evaluated. C does not support parameter transmission using call by name scheme. A programming language that supports call by name scheme is ALGOL 60.


Call by reference

Call by reference is perhaps the most common parameter transmission mechanism. When a data object is transmitted as a call by reference parameter, a pointer (i.e. its address or l-value) to the location of the data object corresponding to the actual parameter is used to initialize local storage location of the associated formal parameter.

Implementation of call-by-reference parameter involves two stages:

  1. In the calling function, each actual parameter expression is evaluated to give a pointer to the actual parameter data object i.e., its l-value. A list of these pointers is stored in a common storage area that is also accessible to the function being called. Control is then transferred to the called function and the activation record for the called function is created, the return point is established, and so on.
  2. In the called function, the list of pointers to actual parameters is accessed in order to retrieve the appropriate r-values for the actual parameters.

Note: l-value refers to left value or address of a variable. r-value refers to right value or actual value of the variable.

During execution of the called function, references to formal parameter names are treated as ordinary local variable references (except that there may be a hidden pointer selection).

Although C does not explicitly support call by reference scheme, pointer variables in C can be used to indirectly implement call by reference. This feature will be discussed in detail when we introduce pointer data type in subsequent articles.


Call by value

If a parameter is transmitted by value, the value (i.e., r-value) of the actual parameter is copied into the called formal parameter. The implementation mechanism is similar to the call by reference model except that unlike the usage of l-value in the call by reference scheme, here we rely only on the r-value. C supports parameter transfer only by this scheme.

From the preceding discussion, it should be clear that with call by reference we have an alias to the actual parameter, while in call by value we have no such reference. Thus, once an actual parameter is passed by value, the formal parameter cannot change the value of the actual parameter. Any changes made in the formal parameter values during execution of the called function are lost when the function terminates. Therefore, when the call by value scheme is adopted the called function cannot return results to the calling function through parameters. One can only use the return statement as discussed below.

A return statement in a function can return only one value. Hence when multiple data objects have to be returned as a result of function invocation, C requires pointer to such objects to be used as parameters. As discussed above, this means we transfer result data values using the call by reference scheme.


Explicit Function Values

In most languages, a single result may be returned as an explicit function value rather than as a parameter. The called function must be declared, and the type of the result returned must be declared as part of the called function's definition, as in the C declaration:float fn(), which specifies fn to be a function returning a result of type float. Within a C function, the result to be returned as the function value is specified by an explicit result expression given as part of the return statement that terminates execution of the subprogram, e.g.return(2*x); indicates that the value of 2 * x is to be returned as the function value.


Let us re-capitulate what we have learnt so far by looking at another example.

 /* calling subprogram */
 void calling_sub()
 {
	int x, y;
	x = 4;
	y = 5;
	called_sub(x, &y);
	printf("%d %d\n", x, y); //this will print after called_sub returns
 }
 /* called subprogram */
 void called_sub(int a, int *b)
 {
	a = a + 6;
	*b = *b + 5;
	printf("%d %d ", a, *b); //this will print first
	return;
 }

The above example shows the listing of a C subprogram called_sub and calling_sub. The called_sub is invoked with two formal parameters - a, transmitted by call by value scheme, and b, transmitted by a sort of call by reference scheme. The program calling_sub calls called_sub with an integer variable, x and a pointer to an integer &y, as actual parameters. The results printed by the two printf statements at the end of execution of calling_sub are: 10 10 4 10. Let us discuss in detail about each parameter in turn.

When calling_sub invokes called_sub, the actual-parameter expressions x and &y are checked; i.e., a referencing operation is invoked to determine the current association of the variable names x and y. Each variable represents an integer data object, so the actual parameters transmitted are the r-value of x and l-value of y. Since x is being transmitted by call by value scheme, formal parameter a is treated as a local integer variable within called_sub. When function called_sub begins execution, the value of x at the time of the call is assigned as the initial value of a. Subsequently, x and a have no further connection. Thus, when a is assigned the new value 10, x is not changed. After the call to called_sub is complete, x still has the value 4.

Parameter y, on the other hand, is transmitted by a sort of call by reference scheme. This indicates that b is a local variable in called_sub of type pointer to integer. When called_sub begins execution, the l-value of the data object y is stored as the r-value of b. When 5 is added to the value of b, b itself does not change. Instead, the reference to b (the r-value of b, which is the l-value of y) actually gives access to the location of the data object y. As a result the assignment to b actually means something quite different. The value of actual parameter y is changed to 10. When the values of the formal parameters a and b are printed in called_sub, the results are 10 and 10. After returning to calling_sub, when the values of the corresponding actual parameters x and y are printed, only y has changed value.


Exercises:

Predict the output generated by each of the following programs:

 #include <stdio.h>
 main()
 { 
	int x, ctr;
	int f1(int ctr);  
	for(ctr = 1; ctr < = 5; ++ctr) 
	{ 
		x = f1(ctr);
		printf("%d", x);
	}
 }
	
 int f1(int a)
 {
	int b = 0;
	b += a;
	return(b);
 }
 #include <stdio.h>
 main()
 { 
	int x = 0,ctr;
	int f1(int ctr);
		
	for(ctr = 1; ctr <= 10; ++ctr)
	{
		x = f1(ctr);
		printf("%d", x);
	}
 }
	
 int f1(int a)
 {
	static int b = 1;
	b *= a;
	return(b);
 }
 #include <stdio.h>
 main()
 { 
	int x = 0, y = 1,ctr;
	int f1(int x);
	int f2(int y);
	for(ctr = 1; ctr <= 5; ++ctr)
	{
		y += f1(x) + f2(y);
		printf("%d",y);
	}
 }
 
 int f1(int x)
 {
	int y;
	int f2(int y);
	y = f2(x);
	return(y);
 }
	
 int f2(int y)
 {
	static int y = 1;
	y * = 2;
	return(y * x);
 }
 #include <stdio.h>
 int x = 5;
 main()
 { 
	int ctr;
	int f1(int a);
	for(ctr = 1; ctr <= 4; ++ctr)
	{
		x = f1(ctr);
		printf("%d",x);
	}
 }
	
 int f1(int a)
 {
	x += a;
	return(x);
 }
 #include <stdio.h>
 int x = 10, y = 20;
 main()
 { 
	int a,b,ctr;
	int f1(int a, int b); 
	for(ctr = 1; ctr <= 3; ++ctr)
	{
		a = 10 * (ctr  1);
		b = 2 * ctr * a;
		printf("%d %d \n", f1(x,a), f1(y,b));
	}
 }

 int f1(int j, int k)
 {
	return(j + k);
 }
 #include <stdio.h>
 int x = 10, y = 20;
 main()
 { 
	int ctr;
	int f1(int ctr);		
	for(ctr = 1; ctr <= 4; ++ctr)
	printf("%d\n",f1(ctr));
 }
	
 int f1(int a)
 {
	int c,d;
	int f2(int c);	
	c = f2(a);
	d = (c < 10)? (x  c): y;
	return(d);
 }

 int f2(int a)
 {
	static int mult = 2;
	mult *= a;
	return(mult);
 }
 #include <stdio.h>
 int cnt = 0;
 main()
 { 
	void f1(void);
	printf("please enter a line of text below \n");
	f1();
	printf(" Number of characters entered %d ", cnt);
 }

 void f1(void)
 {
	char c;
	if((c = getchar()) != '\n')
	{
		++cnt;
		f1();
	}
	return;
 }

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.