text: ¤ Home » Programming » C Tutorial » 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:
  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.
  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.
  #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 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 as
  float 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.
  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 program’s 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.
  #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 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.
  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++; } }
  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)); }
  c2 = a2 + b2
  C = M[(1 + i/100) + ( 1 + i/100)2 + ( 1 + i/100)3 + ... + ( 1 + i/100)n]
  Data Input and Output functions in C
  Functions in C – Part 1 of 5
  Functions in C – Part 2 of 5
  Functions in C – Part.