How2Lab Logo
tech guide & how tos..


Functions in C - Part 4 of 5


We have seen that a C program consists of blocks of statements and expressions. These blocks are enclosed within curly braces { }, and could form a section of the main body of the program (such as if-else statement block, loop block, etc.), or could be a function.

The terms expression and statement are often interchangeably used. A C statement itself may be an expression. For example -
area = PI * r * r;
is a C expression as well as a statement. As you can see in this example, the expression is made up of operators (=, *) and operands (area, PI, r). There are two types of operands here PI, which is a constant defined in the math library as 3.14; and area & r, which we have referred earlier as variables. These variable and constant names are also referred as identifiers.

We have already seen that constants are defined (not declared). Example#define PI 3.14. We have also mentioned that all such define (and include) are not C statements. They are directives to the C compiler and whenever the compiler encounters a define directive such as PI, it will replace all occurrences of symbol PI in the C program with the defined value 3.14, before beginning the program compilation. Hence scoping rules are not applicable for constants. So, when we discuss about scoping rules and storage class, we will be discussing in the context of variables and not constants.

A C program is normally made up of several functions. Variables can be declared within a function or outside the functions. Variables are also passed from one function to another through the parameters of the called function. A C program may also run into multiple files. The questions one may ask are:

  1. What is the scope of a variable that is declared within a function or within a block (enclosed by curly braces)?
  2. What is the scope of a variable that is declared outside all functions defined in the program?
  3. How do we extend the scope of a variable that is declared in one file, to other files?
  4. You may often encounter that same identifier name is declared at two places, which may cause name conflicts. How does C treat such name conflicts?

We will understand the above by understanding the scope rules of variables in C and their storage class.

The point of discussion is at what point in the C program should we declare/define the variables/identifiers, and what will be their scope of identification, i.e. in what portion of the C program (viz., in which blocks) will the declared identifiers be recognizable/identifiable. This brings us to the topic of scope rules of variables in C.

Further, we have mentioned earlier that when functions are called, an activation record for each function call is dynamically created and this activation record is dynamically destroyed after the function returns. Naturally, one would tend to think that all variables declared within the function will be destroyed once the activation record is destroyed. However, there could be situations where a particular variable declared within a function needs to be accessed even after the function has returned, which means that it must exist in the memory even after the function's activation record is destroyed. This brings us to the topic of storage class in C. Thus, storage class refers to the permanence of a variable and its scope within a program.


C allows four different storage class specifications.

  1. Automatic
  2. External
  3. Static
  4. Register

Automatic variables

Automatic variables are always declared within a function and are local to the function in which they are declared; their scope is limited to that function. Automatic variables defined in different functions will be independent of one another, even though they may have the same name. Unless otherwise specified, a variable declared within a function is treated as an automatic variable. No keyword auto is required for such variable declarations.

Automatic variables can be initialized/assigned with a value during declaration. Such values can be reassigned in statements within the function. These variables do not retain values once control is transferred out of the function because the function's activation record is destroyed once function returns control back to the calling function, and so the automatic variables are also destroyed.

Example:
 #include <stdio.h>
 #define PI 3.14

 main()
 {
	/* automatic or local variables */
	float area;
	int r = 20;

	area = PI * r * r;
	printf("Area = %f\n", area);
 }


External variables

External variables are not confined to a single function. Their scope extends from the point of declaration through the remainder of the program. Such variables may be referenced by all functions in that source file which are defined beyond the external variable declaration, and are therefore global to those functions. An external variable declaration must begin with keyword extern. This keyword however is not required in the definition of this variable. Storage space for external variables will not be allocated as a result of an external variable declaration. Therefore, external variable declaration cannot include any assignment of initial values. Note that in case of automatic variables, both declaration and definition were done through the same statement such asfloat area;. However, in case of external variables, the declaration and definition are not the same.

The definition of an external variable is done in the same manner as an automatic variable, but it must appear outside the functions that access the external variable. The definition allocates storage space for the external variable and hence an initial value can be assigned at the same time, if required.

Let us look at an example to understand this better:

 #include <stdio.h>
 int counter = 0; ///external variable definition & initialization

 main()
 {
	...
	...
 }

 float price_list[30]; //another external variable definition
 float calculate_price() 
 {
	...
	...
 }

In the above example, the variables counter and price_list are defined externally and they can be accessed in the functions that follow from the point of their definition. In case the variable price_list is to be accessed before its definition, say in function main, or in case it is to be accessed in an external program file (note that a C program can be written in multiple files), then an extern declaration becomes mandatory.

Note that the external variable definition is done only once among all the files that make up the source program. Whereas, more than one extern declaration of it may be done in each of those functions that wish to access it but are defined before its declaration, or are defined in an external file.

So to access price_list in function main() the program is modified as follows:

 ...
 main()
 {
	extern float price_list[]; //extern declaration
	...
 }

Note that in the above extern declaration, since no space is allocated, we do not specify the array size 30.


Let us look at a multi-file case of external variable declaration and definition:

 /* FILE 1 */
 ...
 #define MAX_STUD 100
 int grades[MAX_STUD]; //external variable definition
 main()
 {
	...
 }
 /* FILE 2 */
 ...
 extern int grades[]; //external variable declaration
 float average()
 {
	...
 }

We will see later how multi-file programming can be done in C.



Static variables

The name static is given from the fact that such variables are given a static space allocation in the computer memory.

In certain situations it may be desirable to define a variable within a function for which storage should remain allocated throughout the execution of the program. For example it might be useful to maintain a local counter in a function (that is invoked multiple times), that would indicate the number of times the function is invoked. This can be done by pre-fixing a keyword static in the variable declaration. A static internal variable is local to that function but remains in existence throughout the programs execution. This means that on every call to the function, when the function returns, the space allocated to the static variable is not destroyed and hence it retains its last value.

You can also have static external variables. A static external variable is allocated storage only once, but may be referred to by any function that follows it in the source file.

Note that static variables can be initialized only by constant values and not by expressions.


Example:
 #include <stdio.h>

 long int fibonacci(int n) 
 { 
	static long int f1 = 1, f2 = 2; 
	long int f; 
	f = (n <3) ? 1: f1 + f2; 
	f1 = f2;
	f2 = f; 
	return (f); 
 } 

 main()
 {
	int m,n; 
	long int fibonacci(int m);
	scanf("%d", &n);
	for(m = 1; m <= n; ++m)
		printf("\nI = %2d, F = %ld", m, fibonacci(m));
 }


Register variables

Register variables are defined using a keyword register in the declaration of an automatic variable or in the formal parameter of a function. There are several machine dependent restrictions on such variables. The register variables are discussed later in the article on Low Level Programming.


Exercise:

How many times will the for loop in the function main() be executed?

 int i = 5, j = 10;
 void slip(void)
 {
	int j = 1;
	static int n = -3;
	i += n++ + j++;
 }

 main()
 {
	for(; i < j; i++)
	{
		slip();
		j++;
	}
 }


Multiple file declaration

The following example illustrates usage of external declaration when a program spans over multiple files.

 //FILE 1
 #include <stdio.h>
 double a, b, x1, y1, const = 0.0001;
 extern void reduce(void);
 extern double curve(double x1);

 main()
 {
	double smax, ymax;
	...
	reduce();
	...
	ymax = curve(xmax);
	...
 } 
 //FILE 2
 extern double a, b, x1, y1, const;
 extern double curve(double x1);
 void reduce(void)
 {
	/* code for reduce */
	...
	return;
 }
 //FILE 3
 #include <stdio.h>
 double curve(double x)
 {
	/* code for curve */
	...
	return(x * cos(x));
 }


Lab Work

  1. Three integer number a, b and c are called Pythagorean numbers if
    c2 = a2 + b2
    Thus 3, 4 and 5 are Pythagorean triplets. Write a C program to find all Pythagorean triplets less than a given integer number N.

  2. Suppose a sum of money, ? M is deposited into a savings bank account at the beginning of each year for n years. The bank gives interest at the rate of i percent which is compounded annually. Therefore, after n years the amount saved can be calculated as,
    C = M[(1 + i/100) + ( 1 + i/100)2 + ( 1 + i/100)3 + ... + ( 1 + i/100)n]

    Write an interactive C program using suitable functions, to determine the following:

    (a) How much money will get accumulated after 30 years if ? 1000 is deposited at the beginning of each year and the interest rate is 6% per year compounded annually?

    (b) How much money must be deposited at the beginning of each year in order to accumulate ? 100,000 after 30 years, again assuming the annual rate of interest is 6% per year compounded annually?

  3. A circle C can be completely specified by the co-ordinates of its center (x, y) and the radius (R). Given two circles C1 and C2 test the following:

    (a) C1 intersects C2 or not.
    (b) C1 touches C2 or not, if so, whether internally or externally.
    (c) Circle C1 completely embeds circle C2 or not.

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.