Functions

Functions

  • Rules of functions
  • Examples - writing a function, calling a function
  • Function prototypes
  • Visibility
  • Call by value
  • The stack
  • auto, static and register

 

The Rules

  • A function may accept as many parameters as it needs, or no parameters (like main)
  • A function may return either one or no values
  • Variables declared inside a function are only available to that function, unless explicitly passed to another function 

 

Writing a Function - Example

  • In below example the int is the TYPE of the value handed back.
  • And here there are 3 parameters are accepted
1
2
3
4
5
6
7
8
9
10
11
int print_table(double start, double end, double step) 
{ 
	double d; 
	int lines = 1; 
	printf("Celsius\tFarenheit\n"); 
	for(d = start; d <= end; d += step, lines++)
 	{
		printf("%.1lf\t%.2lf\n", d, d * 1.8 + 32); 
    }
	return lines; 
}

 

 

Calling a Function - Example

  • In main programme, the compiler knows these should be doubles & converts them automatically
  • The 2nd line tells the compiler how print_table works
  • Then the line no 9 says the function's return value is ignored- this is ok, if you don't hsve to use it

 

1
2
3
4
5
6
7
8
9
10
11
12
#incluede <stdio.h>
int print_table(double, double, double);
int main (void)
{
  int how_many;
  double end = 100;
  
  how_many = print_table(1.0, end, 3);
  print_table(end, 200, 15);
  
  return 0;
}

 

 

Prototypes


The (optional) line

1
int print_table(double, double, double);

 is known as a prototype

  • If the compiler meets a call to an unknown function it “guesses”
    — Guess 1: the function returns an int, even if it doesn’t
    — Guess 2: you have passed the correct number of parameters and made sure they are all of the correct type, even if you haven’t
  • The prototype provides the compiler with important information about the return type and parameters

 

Prototyping is Not Optional

  • To achieve working programs the compiler is best given a prototype for each function called
  • When calling a Standard Library function, #include the file specified in the help page(s) - this file will contain the prototype
  • When calling one of your own functions, write a prototype by hand

 

 

Writing Prototypes

  • Prototype:
1
int print_table(double, double, double);

 

  • Function Header:
1
2
int pritnt_table(double start, double end, double step)
{

 

  • The function prototyupe may optionally include variable names(which are ignored)
1
int pritnt_table(double start, double end, double step);

 

1
int pritnt_table(double x, double y, double z);

 

 

Take Care With Semicolons

  • The prototype has a semicolon
1
int pritnt_table(double start, double end, double step);

 

  • The Function Header has an open brace
1
2
int pritnt_table(double start, double end, double step)
{

 

  • Don't counfudse the compiler by adding a semicolon into the function header
1
2
int pritnt_table(double start, double end, double step);
{

 

 

Examples Prototypes :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* no parameters, int return value */ 
int get_integer(void); 
 
/* no parameters, double return value */
double get_double(void); 
 
/* no parameters, no return value */
void clear_screen(void);
 
/* three int parameters, int return value */
int day_of_year(int day, int month, int year); 
 
/* three int parameters, long int return value */
long day_since_1_jan_1970 (int. int, int); 
 
/* parameter checking DISABLED, double return value */
 double k_and_r_function();
 
/* short int parameter, (default) int return value */
transfer(short int s); 

 

 

Example Calls

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int i;
double d;
long l;
short int s = 5;
 
i = get_integer();
d = get_double();
clear_screen();
 
i = day_of_year(16, 7, 1969);
l = day_since_1_jan_1970(1, 4, 1983);
 
d = k_and_r_function();
d = k_and_r_function(19.7);
d = k_and_r_function("hello world");
 
i = tranfer(s);

 

  

Call by Value

  • When a function is called the parameters are copied - “call by value”
  • The function is unable to change any variable passed as a parameter
  • In the next chapter pointers are discussed which allow “call by reference”
  • We have already had a sneak preview of this mechanism with scanf 

 

Call by value Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
void change(int v);
 
int main (void)
{
  int var = 5;
  change(var);
  printf("main: var = %i\n", var);
  return 0;
}
 
void change(int v)
{
  v *= 100;
  printf("change: v = %i\n", v);
}

 

In above example, the function was not able to alter "var" which is denoted in line no 8.

Also in line 14, the finction is able to alter "v". The value of "v" is mentioned in below result.  

Result :

1
2
change:c v = 500
main: var = 5

 

C and the Stack

  • C uses a stack to store local variables (i.e. those declared in functions), it is also used when passing parameters to functions
  1. The calling function pushes the parameters
  2. The function is called
  3. The called function picks up the parameters
  4. The called function pushes its local variables
  5. When finished, the called function pops its local variables and jumps back to the calling function
  6. The calling function pops the parameters
  7. The return value is handled

 

Stack Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
double power(int, int);
 
int main(void)
{
  int x = 2;
  double d;
  d  = power(x, 5);
  printf("%1f\n", d);
  return 0;
}
 
double power(int n, int p)
{
  double result = n;
  while(--p > 0)
    result *= n;
  return result;
}

 

Result :

1
2
3
4
5
6
32.0 power:result
 2	 power:n
 5   power:p
----------------
 ?   main:d
 2   main:x 

 

Storage

  • C stores local variables on the stack
  • Global variables may be declared. These are not stack based, but are placed in the data segment
  • Special keywords exist to specify where local variables are stored: 

         auto - place on the stack (default)

         static - place in the data segment

         register - place in a CPU register

  • Data may also be placed on the heap, this will be discussed in a later chapter

 

auto

  • Local variables are automatically allocated on entry into, and automatically deallocated on exit from, a function
  • These variables are therefore called “automatic”
  • Initial value: random
  • Initialisation: recommended

 

Example :

1
2
3
4
5
int table(void)
{
  int lines = 13;
  auto int columns;
}

 

Here in line no 4, auto keyword is redundant. 

 

 

static

  • The static keyword instructs the compiler to place a variable into the data segment
  • The data segment is permanent (static)
  • A value left in a static in one call to a function will still be there at the next call
  • Initial value: 0
  • Initialisation: unnecessary if you like zeros

Example :

1
2
3
4
int running_total(void)
{
  static int rows;
  rows++;

 

Here, "rows" is permanently located, but local to this function.

 

register

  • The register keyword tells the compiler to place a variable into a CPU register (you cannot specify which)
  • If a register is unavailable the request will be ignored
  • Largely redundant with optimising compilers
  • Initial value: random
  • Initialisation: recommended
1
2
3
4
void speedy_function(void)
{
  register int i;
  for(i =  0; i < 10000; i++)

 

 

Global Variables

  • Global variables are created by placing the declaration outside all functions
  • They are placed in the data segment
  • Initial value: 0
  • Initialisation: unnecessary if you like zeros
1
2
3
4
5
6
7
8
#include <stdio.h>
 
double d;
int main(void)
{
  int i;
  return 0;
}

 

Here variable "d" is global and available to all functions defined below it.

 

 

 

 

 

 

 

 

 

 

About Us

  • Micromagine Embedded System Design
    3rd Floor,
    Triveni Sangam Appartment,
    Opp. Divyabhaskar Office,
    Kishan Para Chowk,
    Rajkot - 360001

  • info@micromagine.com
    info@micromagine.com

  • (+91) 9429160113

Services & Support

Premium Joomla Templates