LECTURE 17

FUNCTIONS

IN FORTRAN :

! THIS PROGRAM COMPUTES THE CUBE OF ITS INPUT.
REAL FUNCTION CUBE(X)
IMPLICIT NONE
REAL :: X
CUBE = X * X * X
END FUNCTION CUBE

IN C :

/* This program computes the cube of its input */
real cube (x)
float x;
{
return (x * x * x);
}

SIMILARITIES :

• A function can return 1 value of specified type

Function calls can be used in expressions

DIFFERENCES :

• FORTRAN uses special variable (same name as function) to hold return value
• C uses return statement to specify return value

SUBROUTINES

In FORTRAN :

! THIS PROGRAM PRINTS N STARS (N<=100)
SUBROUTINE STARS(N)
INTEGER, INTENT( IN ) :: N
PRINT 5,('*',I=1,N)
5 FORMAT(' ',100A1)
END SUBROUTINE STARS
...
CALL STARS (NSALES)

In C :

In C, a subroutine is just a function that returns a ''void'', and is called like a function (no CALL keyword).

/* This program prints n stars */

void stars (n)
int n;
{
int i; /* local variable */
for (i=1; i<=n; i+=1)
{
putchar ('*') ;
}
putchar ('\n') ;
return ;
}
...
stars (nsales) ;

• Break up large software
• Separate compilation
• Independent development by team members
• Share common type declarations
• Share common functions, data
• Create library of useful functions
• Easy to modify one piece independently

Example of #define and its Use

#include < stdio.h >
#define PI 3.14159
#define SQUARE(X) ( (X) * (X) )

main ( )
{
clrscr( ) ;
area = 2 * PI * SQUARE ( radius ) ;
printf (''Area of a circle of radius r = %f is %f'', radius, area ) ;
}

Example showing need for parentheses in #define directive

#include < stdio.h >
#define PI 3.14159
#define SQUARE(X) ( X * X )

main ( )
{
clrscr( ) ;
area = 2 * PI * SQUARE ( radius + 1.0 ) ;

/* Here SQUARE will compute ( radius + 1.0 * radius + 1.0 ) which is not what we want. This     give ( 2*radius + 1.0 ) instead of ( ( radius + 1.0 )* ( radius + 1.0 ) ) */

printf (''Area of a circle of radius r =%f is %f'', radius, area);
}

Code illustrating the difference between function and #define

#include <stdio.h>

#define SQUARE( X ) ( (X) * (X) )

int square(int x)
{
return(x*x)
}

main ( )
{
int i = 3 ;
int j ;
clrscr( ) ;
j = square (i) ;

printf ( '' Square of %d = %d \n'', i, j ) ;

j = SQUARE (i) ;

printf ( '' Square of %d = %d'', i, j ) ;
}
Output :
Square of 3 = 9

Square of 3 = 9

Using function to average elements of an array

float average_floats ( float x [ ], int n )
/*
where x is the array of elements and n the number of elements
*/
{
float average = 0.0 ;
int i ;
for( i = 0 ; i < n ; i++ ) average + = x [ i ] ;
return(average/n) ;
}

THREE IMPORTANT CONCEPTS

For a variable x : EXAMPLE

1) VALUE OF X is -27

2) ADDRESS OF X is &X

3) POINTER TO X is *POINTER_X

EXAMPLE : USE OF POINTER

int x, *pointer_x ; /*declaration of variable x and pointer x */

x = -27 ; /* Assigning -27 to variable x */

pointer_x = &x ; /* Let pointer_x ''pointing'' to the address of variable x */

*pointer_x = -54;  /* Assigning the value -54 to pointer_x also assigns -54
to variable x */

POINTER DATA TYPE

• C allows for call-by-reference through use of pointers.
• A ''pointer'' is a reference to an object of a specific data type. ( An int pointer and a float pointer are not the same thing. )
• Pointers are stored in pointer variables.

DECLARING POINTERS

int x,y ;

int *px, *py ;

CREATING POINTERS USING &

px = &x ;
py = &y ;

ACCESSING OBJECTS VIA POINTERS :

y = *ptr1 ; /* Read, and then write, the */

*ptr1 = 4 ; /* variable pointed to by ptr1 */

COPYING POINTERS :

ptr1 = ptr2 ;

if (ptr1 == ptr2) printf ("They point to the same thing\n") ;

CALL-BY-VALUE

• In FORTRAN functions and subroutines, dummy variables are merely ''references'' or ''aliases'' for variables or constants in the calling program.
• Careless assignment to the dummy variables can inadvertently change variables - even constants - in the calling program.
• In C, dummy variables ( if single objects ) get a copy of the value from the calling program.
• Reassigning to dummy variables has no effect on variables in the calling program. Thus, stars can be rewritten to eliminate the local variable :
/* This program prints n stars */

void stars (n) int n;
{
for ( ; n > 0 ; n -= 1 )
{
putchar ('* ') ;
}
putchar ('\n') ;
return;
}

• No danger of changing data in calling routine
• Can modify input values ( as in stars ), thereby making code more compact
• Cleaner and more intuitive -- like mathematical concept of '' function ''

• Functions can't return more than one value
• Can't write '' swapping '' routines
• Can't pass compound data (e.g., arrays) because copying is too costly

CALL-BY-REFERENCE

IN FORTRAN :

PROGRAM REFERENCE
IMPLICIT NONE
REAL :: A,B
INTERFACE
SUBROUTINE SWAP(X,Y)
IMPLICIT NONE
REAL, INTENT(IN OUT) :: X,Y
END SUBROUTINE SWAP
END INTERFACE
...
CALL SWAP(A,B)
...
STOP
END PROGRAM REFERENCE
! THIS PROGRAM SWAPS ITS TWO INPUTS
SUBROUTINE SWAP(X,Y)
IMPLICIT NONE
REAL, INTENT(IN OUT) :: X,Y
REAL :: TEMP
TEMP = X
X = Y
Y = TEMP
END SUBROUTINE SWAP

IN C ( USING POINTERS )

main ( )
{
float a,b;
...
swap (&a, &b) ;
...
}
/* This function swaps its two inputs. */
void swap(float *ptrx, float *ptry)
{
float temp ;
temp = *ptrx ;
*ptrx = *ptry ;
*ptry = temp ;
}