Passing information to and from a function Function Parameters Passing information to and from a function Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Parameter Questions What can be passed? Variables Constants Expressions Functions Can the called function change the variable? Copyright © 2006-2016 - Curt Hill
Parameter Passage Mechanisms C had two parameter passage mechanisms: By value By pointer C++ has these two and one additional By reference First however some definitions Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Definitions int func(int a, double b){ … } … x = func(x,y)*2 - func(w,z); Formal parameters are part of the definition Actual parameters are part of the call For any one function only one set of formals but perhaps many sets of actuals The names do not have to match Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Formal parameters The formal parameter list determines everything It defines the rules that everyone else plays by The number of parameters The type of each parameter The parameter passage mechanism Value, pointer or reference Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Communication A function that does not communicate with its caller is worthless There are three mechanisms for communication: Parameters Function result Global variables Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Direction Parameters may carry information in to or out of a function or both We sometimes refer to parameters as in, out or in-out Function results are out only Global variables can carry information in either direction They are also the least desirable communication mechanism for reasons to be seen later Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Parameter Names The formal parameter names do not have to match anything Not the actual parameter names On any others They have the same scope as the local variables of the function The prototype does not even have to specify names: double pow(double,double); is legal Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Parameters So far we have only seen value parameters Value parameters are noted in the formal parameter list by: type name A value parameter may only take information into a function The function receives a copy of the value of the actual parameter Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill For each value parameter a new variable is created This new variable is initialized with the value from the actual parameter When the function returns the variable is destroyed Any changes to the value parameter remain in the function and are not communicated back to the caller An in parameter Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill What can the Actual be? With a value parameter the actual is copied to the formal parameter anything that is assignment compatible will work Thus the actual may be a: A constant, variable or expression Of any type that may be cast into the type of the formal parameter Lots of flexibility Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(0) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main i 2 j 3 k 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(1) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main i 2 j 3 k 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(2) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 k 5 i 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(3) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 k 5 i 2 j k 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(4) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 k 5 i 2 j 4 k 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(5) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 k 5 i 2 j 4 k 2 Test is false Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(6) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 k 5 i 2 j 4 k 2 Changing formal parameter does not change actual Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(7) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 k 5 i 2 j 4 k 2 Return value is 0+4-2 = 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(8) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main i 2 j 3 2 k 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(9) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main i 2 j 3 2 k 5 Output 2 2 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(10) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main i 2 j 3 2 k 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(11) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 2 k 5 i 4 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(12) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 2 k 5 i 4 j k 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(13) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 2 k 5 i 4 j 8 k 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(14) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 2 k 5 i 4 j 8 k 2 Test is true Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(15) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 2 k 5 i 4 j 8 k 2 10 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(16) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 2 k 5 i 4 2 j 8 k 2 10 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(17) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main func i 2 j 3 2 k 5 i 4 2 j 8 k 2 10 Return value is 2+8-10 = 0 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(18) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main i 2 j 3 2 k 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Value Trace(19) int func(int i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j <<k << “\n”; k = func(i+j); cout << i << j << k<< “\n”; main i 2 j 3 2 k 5 Output 2 2 0 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Commentary Copy into a console program in Dev and try it Trace it results should be: 2 2 5 2 2 0 Look out for PPT line endings which usually show as a rectangle Parameters are passed by value Functions may not access each others local variables Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill What is missing? Value parameters may be input only That is they may only carry values into the function How are out or in-out parameters handled Two ways: Pointer parameters Available in C Not covered until later Reference parameters Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference parameters A value parameter receives a copy of the actual parameter Thus a constant may be passed A reference parameter receives the actual variable Thus it may change the value of the variable It restricts what may be passed in the actual parameter Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Form of the Formal The mark of a reference parameter is the ampersand (&) The form of the reference parameter is: type & name For example: int fn(int & a, float b, double & c) Two reference parameters One value parameter No space needed before or after & Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Actual Parameters This also changes the form of actual parameters The actual must be a variable No constants and no expressions It must be of exactly the same type The purpose of a reference parameter is to change the variable How do you change a constant or expression? Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reconsider the trace Now lets consider the previous program It will now have two ways to return values: The reference parameter The function result The second call of the first program is now illegal and thus must be changed Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(0) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main i 2 j 3 k 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(1) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main i 2 j 3 k 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(2) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 k 5 i func’s i is now an alias for main’s i Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(3) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 k 5 i j k 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(4) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 k 5 i j 4 k 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(5) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 k 5 i j 4 k 2 test is false Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(6) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 k 5 i j 4 k 2 The two i variables are changed Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(7) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 k 5 i j 4 k 2 0 +4-2 = 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(8) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main i 2 j 3 2 k 5 Returned 2 is set into j Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(9) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main i 2 j 3 2 k 5 Output 0 2 5 Last time it was 2 2 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(10) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main i 2 j 3 2 k 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(11) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 2 k 5 i func’s i is now an alias for main’s j Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(12) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 2 k 5 i j k 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(13) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 2 k 5 i j 4 k 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(14) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 2 k 5 i j 4 k 2 test is false Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(15) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 2 k 5 i j 4 k 2 main’s j is changed Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(16) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main func i 2 j 3 2 k 5 i j 4 k 2 0+0-2 = -2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(17) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main i 2 j 3 2 k 5 -2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference Trace(18) int func(int & i) { int j,k=2; j = k * i; if (j>k*2) k+=j; i = i - 2; return(i+j-k); } int main (void) { int i=2,j=3,k=5; j = func(i); cout<< i << j << k << “\n”; k = func(j); cout << i << j << k << “\n”; main i 2 j 3 2 k 5 -2 Output is 0 0 -2 Last time it was 2 2 0 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Contrast A value parameter always provides a copy A reference parameter is an alias A new name on an old thing Value parameters have flexible actual parameters Reference parameters have rigid actuals Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Copy Overhead The only in parameter is a value parameter The copying of the value may be a problem On simple variables this is no problem since the copy is small What if the item is a class or other structure and the size is large Say greater than 10,000 bytes Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Solution We could copy it by reference However it is in-out We could change it by mistake and introduce a bug C++ introduces a new mechanism to solve this problem: Constant reference parameters Copyright © 2006-2016 - Curt Hill
Constant Reference Parameters Prefix a reference parameter with the reserved word const: const type & name This is used to get in only parameters, but to avoid the copy overhead The compiler will issue a syntax error on code that attempts to change a constant parameter Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Reference parameters are new to C++ Constant reference also C had only value and pointer C also went through several revisions The form of parameter declarations changed Started with FORTRAN style parameters Moved towards Pascal style parameters These are what we have seen Copyright © 2006-2016 - Curt Hill
FORTRAN style parameters Since there is still quite a bit of old style code around it is best if you see both at least once Thus we will look at the same function using both styles of parameter declaration Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill New Style Suppose that we have the following: double partial_factorial (int n, int k) { double fact=1.0; int i; for (i=k+1;i<=n;i=i+1) fact *= fact; return(fact); } Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Old Style Suppose that we have the following: double partial_factorial(n, k) int n,k; { double fact=1.0; int i; for (i=k+1;i<=n;i=i+1) fact *= fact; return(fact); } Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Notes The parameter list contains only the names of the parameters Between the end of the parameter list and the opening brace is the declarations of the parameters Inside the braces are local variables You may still see this kind of notation in various places: Windows programming documentation Code found on internet Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Another Thought C++ still accepts FORTRAN style parameters With very rare exceptions every valid C program should compile in C++ This is one of the disadvantages of upward compatibility Java started fresh Used most of good parts of C++ Ignored rest Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Scope Each pair of braces forms its own scope block Function braces are no exception The formal parameter list is sort of the odd ball The names of the formal parameters are only known within the function The prototype may leave the names out Somewhat similar to the declaration of a variable in a for header Copyright © 2006-2016 - Curt Hill
Consider the following double partial_factorial(int n, int k) { double fact=1.0; for (int i=k+1;i<=n;i=i+1) fact *= i; return(fact); } What is known where? Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Answers Any code that follows partial_factorial knows: partial factorial exists as a function It returns a value of type double It takes two parameters, both integers However, the names of the parameters and all local variables are not accessible to this code Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Formal parameters Unusual scope Outside the function the code knows the number and type of the parameters, but not the names The scope of the names of the parameters is confined to the compound statement that is the body of the function Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Globals Identifiers that have global scope will be known to both the function and its caller These may be used to communicate between the two This is not the best form of communication but it works See the following example Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(0) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 global v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(1) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 global v 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(2) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 global v 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(3) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j k 2 global v 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(4) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j 4 k 2 global v 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(5) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j 2 k 2 global Test is false v 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(6) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j 2 k 2 global v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(7) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j 2 k 2 global 0 + 2 -2 = 0 v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(8) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 global To use the global like a parameter, assign v back to i. v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(9) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 global Output: 2 0 5 0 v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(10) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 global v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(11) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 global v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(12) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j k 2 global v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(13) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j k 2 global v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(14) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j k 2 global Test is false v Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(15) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j k 2 global v -2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(16) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main func i 2 j 3 k 5 j k 2 global -2 + 0 -2 = -4 v -2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(17) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 -4 global v -2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Global Trace(18) int v; int func() { int j,k=2; j = k * v; if (j>k*2) k+=j; v = v - 2; return(v+j-k); } int main (void) { int i=2,j=3,k=5; v = i; j = func(); cout<< i << j << k << << v; v = j; k = func(); cout << i << j << k << v; main i 2 j 3 k 5 -4 global Output: 2 0 -4 -2 v -2 Copyright © 2006-2016 - Curt Hill
What is wrong with this code? Additional assignment statement needed func would be difficult to use in other programs Each call needs two statements The definition of the global variable v Both global variables and reference parameters demonstrate side effects Reference parameter side effects are expected Copyright © 2006-2016 - Curt Hill
Communication with functions Function results Out only Value parameters In only Reference parameters In-out Global variables These are ordered in preference Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Commentary If at all possible use only value parameters and function results These are the most obvious and cause the least problem for the one who reads the code Use reference parameters less frequently At least the name appears in the call Use global variables even less frequently Copyright © 2006-2016 - Curt Hill
When to use reference parameters These are best used when more than one output from the function to the caller is needed Also use when a variable may not be copied Often used with void functions Since there is no return value the programmer expects that one or more of the parameters is a reference parameter Copyright © 2006-2016 - Curt Hill
What kind of variable cannot be copied? fstreams cannot be copied ifstreams, ofstreams including cin and cout Why? A file is a peculiar data structure It has pointers to and from the operating system Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill File Picture ifstream inf(“data.dat”); Program side Operating System side inf data.dat OS data Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill A Copy results in: ifstream inf(“data.dat”); Program side Operating System side inf data.dat OS data inf2 data.dat Incorrect structure Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Streams Again Thus a file may not be assigned Nor may it be a value parameter To attempt to do so results in a syntax error What this really means is that the copy constructor is private Thus not accessible An explanation of that statement must await the description of classes Copyright © 2006-2016 - Curt Hill
When to use global variables Seldom To do so ruins reusability, one of the goals of using functions Typically only used when a program has a central data structure This data structure is used by most if not all functions Thus is would end up being a parameter in every call Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Function invocation Better understanding of what going on will occur if we understand how functions are invoked Most modern computers have a built in stack This stack operates at the machine level Items may be pushed on and popped off Lots of things happen on the stack for a call Copyright © 2006-2016 - Curt Hill
In the calling function Each parameter is evaluated and pushed onto the stack Value parameters push on a value Reference parameters push on an address Next the call occurs This pushes on the return address One slot is reserved for the function result if there is one Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill In the called function Value parameters are created and initialized Reference parameters are connected with actual Local variables are created and initialized as needed First statement of function is executed Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Upon return Value is copied upon the stack where the calling function may find it The function returns to the caller This destroys all of the parameters and local variables The caller finds the return value and proceeds Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Some observations: The stack is the location for both parameters and local variables They are truly created and destroyed when the function starts and ends The local variables might or might not be in the same location the next time a function is called You cannot rely on uninitialized variables Copyright © 2006-2016 - Curt Hill
Dynamic vs static storage allocation By default C/C++ uses dynamic (aka automatic) By contrast FORTRAN uses static C++ will allow this by prefixing the variable with static static int a = 5; A static variable retains its value between calls Only initialized once Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static A static variable is like a global variable in that it retains its value from one call to another It is like a local variable in that its scope is local to the function The reserved word static also is used for class variables and functions with different meaning Consider the following traces Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(0) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main m 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(1) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main m 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(2) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 i 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(3) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 i 5 j 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(4) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 i 5 7 j 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(5) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 i 5 7 j 2 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(6) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 i 5 7 j 2 5 returns 7 + 5 = 12 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(7) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main m 5 n 12 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(8) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main m 5 n 12 Output 12 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(9) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main m 5 n 12 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(10) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 i 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(11) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 i 5 j 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(12) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 i 5 7 j 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(13) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 i 5 7 j 2 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(14) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 i 5 7 j 2 5 returns 7 + 5 = 12 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(15) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main m 5 n 12 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Non-static Trace(16) int func(int i){ int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main m 5 n 12 Output 12 again Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Notes The second function call was exactly like the first Every variable had the same value at the beginning so that is what we expect Now we try it again Except make the local static Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(0) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); func j 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(1) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 j 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(2) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 j 2 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(3) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 j 2 i 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(4) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 j 2 i 5 7 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(5) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 j 2 5 i 5 7 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(6) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 j 2 5 i 5 7 returns 7 + 5 = 12 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(7) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 j 2 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(8) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 j 2 5 Output 12 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(9) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 j 2 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(10) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 j 2 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(11) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 j 2 5 i 5 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(12) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 j 2 5 i 5 10 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(13) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 j 2 5 10 i 5 10 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(14) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 j 2 5 10 i 5 10 returns 10 + 10 = 20 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(15) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 20 j 2 5 10 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Static Trace(16) int func(int i){ static int j = 2; i += j; j += i/2; return i+j; } int main(){ int m = 5; int n = func(m); cout << n << "\n"; n = func(m); main func m 5 n 12 20 j 2 5 10 Output 20 Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Last Thought Seldom need static variables in functions We often need static variables and methods in classes Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Some more questions Can a function call another function? Sure Can a function call itself? Can a function access any variable in the main function, its caller, functions it calls? Only those passed as arguments. Can a function be passed as a parameter to another function? Yes Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Recursion A function calling itself is called a recursive function Recursion is the generalization of looping Recursion is mainly considered in the subsequent course However, here is an example Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Factorial Again int facti(int n) { int fact = 1; for(int i = 2; i<=n; i++) fact *= i; return fact; } int factr(int n) { if(n < 2) return 1; return n*factr(n-1); Copyright © 2006-2016 - Curt Hill
Copyright © 2006-2016 - Curt Hill Finally Lots of material in this presentation Not all of it is needed for last programs Understanding the difference between the two parameter passage mechanisms, value and reference, is very important Copyright © 2006-2016 - Curt Hill