Functions, Abstraction & Faculty of Computer Science Dalhousie - - PowerPoint PPT Presentation

functions abstraction
SMART_READER_LITE
LIVE PREVIEW

Functions, Abstraction & Faculty of Computer Science Dalhousie - - PowerPoint PPT Presentation

CSCI 2132: Software Development Norbert Zeh Functions, Abstraction & Faculty of Computer Science Dalhousie University Recursion Winter 2019 Building Abstractions Large projects are built in layers of abstraction! Example: Computer We


slide-1
SLIDE 1

CSCI 2132: Software Development

Functions, Abstraction & Recursion

Norbert Zeh

Faculty of Computer Science Dalhousie University Winter 2019

slide-2
SLIDE 2

Building Abstractions

Large projects are built in layers of abstraction! Example: Computer

  • We don’t design a whole computer using individual transistors as building

blocks!

  • Computer

= CPU, memory, graphics card, ...

  • CPU

= registers, arithmetic/logic unit (ALU), command pipeline, ...

  • ALU

= adders, ...

  • adder

= half-adders, ...

  • half-adders = logic gates, ...
  • logic gates = transistors

Programming = building software abstractions

slide-3
SLIDE 3

Functions

Functions = main abstraction method in programming

  • Sequence of statements that can be used as a single functional

unit

  • Have arguments (input) and return values (output)

Function definition example: int max(int a, int b) { int c; c = (a > b) ? a : b; return c; }

slide-4
SLIDE 4

Function Return Value

  • int by default


(Know to deal with legacy code, never use this in new code!)

  • Arrays cannot be return values (but structs can!)

Example of calling a function:

  • printf(“%d\n”, max(a, b));

Some standard functions:

  • printf:
  • Return value = number of printed characters
  • scanf:
  • Return value = number of read values or EOF if error occurs
slide-5
SLIDE 5

Function Declaration vs Function Definition

Function declaration: Specifies only the argument and return types (Since we only declare the function, the names of the arguments aren’t needed, only their types.) Function definition: Specifies what the function does

int max(int a, int b); int max(int, int); int max(int a, int b) { int c; c = (a > b) ? a : b; return c; }

slide-6
SLIDE 6

Why Declare a Function?

Evaluation order: For historic reasons, C compilers allow you to use a function or variable only after it has been declared. Now consider:

int g(int); int f(int x) { return g(x + 1); } int g(int x) { return (x > 10 ? x : f(x)); }

slide-7
SLIDE 7

#ifndef MAX_H #define MAX_H int max(int, int); #endif MAX_H max.h

Information hiding:

Why Declare a Function?

#include “max.h” int max(int a, int b) {
 return (a < b ? a : b); } max.c

slide-8
SLIDE 8

Function Arguments

The terms arguments and parameters are often used interchangeably. Strictly speaking, they are two different things. Function arguments (or actual parameters):

  • Values passed to a specific call of a function
  • .

max(a, 3 + (b - 1) / 2);

slide-9
SLIDE 9

Function Arguments

The terms arguments and parameters are often used interchangeably. Strictly speaking, they are two different things. Function arguments (or actual parameters):

  • Values passed to a specific call of a function

Function parameters (or formal parameters):

  • Names used to refer to the values passed to a function inside the

function definition.

int max(int a, int b) { return (a < b) ? a : b; } max(a, 3 + (b - 1) / 2);

slide-10
SLIDE 10

Parameter Passing

Different programming languages allow different parameter passing modes:

  • By value:
  • Modifications to the formal parameter inside the function body

does not affect the caller.

  • By reference:
  • Modifications to the formal parameter inside the function body

modify the variable the caller provided as a function argument.

  • By sharing, ...

C passes all values by value. Passing by reference and passing of array arguments accomplished by passing a pointer to the variable by value.

slide-11
SLIDE 11

Example: A Swap Function, 1st Attempt

void swap(int a, int b) {
 int temp = a; a = b; b = temp; } int main() { int a = 4; int b = 5; swap(a, b); printf(“a = %d, b = %d\n”, a, b); return 0;
 }

slide-12
SLIDE 12

Example: A Swap Function, 2nd Attempt

void swap(int *a, int *b) {
 int temp = *a; *a = *b; *b = temp; } int main() { int a = 4; int b = 5; swap(&a, &b); printf(“a = %d, b = %d\n”, a, b); return 0;
 }

slide-13
SLIDE 13

Passing Arrays to Functions

Remember: Arrays are just pointers to their first arguments, no size information. Consequence: Most functions that work with arrays need an extra argument, the size of the array.

  • r

int max_array(int len, int a[]) { ../ } int max_array(int len, int *a) { ../ }

slide-14
SLIDE 14

Multidimensional Array Arguments

Multidimensional arrays can be passed as function arguments. The compiler must know all dimensions, except possibly the first. For 1D arrays, a[] and *a are equivalent. For multidimensional arrays, a[][] and *a[] are not equivalent! Multidimensional array: int f(int a[10][20]) { ../ } int g(float a[][50]) { ../ }

a[0][0] a[1][0] a[1][0] a[1][0] a[0][2] a[0][1]

slide-15
SLIDE 15

Multidimensional Array Arguments

Multidimensional arrays can be passed as function arguments. The compiler must know all dimensions, except possibly the first. For 1D arrays, a[] and *a are equivalent. For multidimensional arrays, a[][] and *a[] are not equivalent! Array of pointers: int f(int a[10][20]) { ../ } int g(float a[][50]) { ../ }

a[1][0] a[1][0] a[1][0] a[0][0] a[0][2] a[0][1] a[0] a[1]

slide-16
SLIDE 16

Variable-Length Multidimensional Arrays

Before C99:

  • Pass a one-dimensional array (or pointer)
  • Do index arithmetic explicitly

int matrix_multiply(int l, int m, int n, float *a, float *b, float *c) { int i, j, k; for (i = 0; i < l; +,i) for (j = 0; j < n; +,j) c[i*n + j] = 0; for (k = 0; k < m; +,k) { c[i*n + j] += a[i*m + k] * a[k*n + j]; } }

slide-17
SLIDE 17

Variable-Length Multidimensional Arrays

C99: int matrix_multiply(int l, int m, int n, float a[l][m], float b[m][n], float c[l][n]) { for (int i = 0; i < l; +,i) for (int j = 0; j < n; +,j) c[i][j] = 0; for (int k = 0; k < m; +,k) { c[i][j] += a[i][k] * a[k][j]; } }

slide-18
SLIDE 18

Variable-Length Multidimensional Arrays

C99: int matrix_multiply(int l, int m, int n, float a[][m], float b[][n], float c[][n]) { for (int i = 0; i < l; +,i) for (int j = 0; j < n; +,j) c[i][j] = 0; for (int k = 0; k < m; +,k) { c[i][j] += a[i][k] * a[k][j]; } }

slide-19
SLIDE 19

Variable-Length Multidimensional Arrays

Notes:

  • The size must precede the array declaration:
  • In declaration, the size parameters can be replaced by *:

int f(int n, int a[][n]) { ../ } int f(int a[][n], int n) { ../ } not int f(int, int a[][*]);

slide-20
SLIDE 20

Pointer Arguments for Efficiency

Remember: All arguments are passed by value.

  • This is costly for large structures
  • Solution: Pass a pointer
  • But: Now the function can modify the referenced data

Solution: const pointer int f(const int *a) { /0 This is okay printf(“%d”, a[3]); /0 This is not a[4] = 0; }

slide-21
SLIDE 21

A Program’s Stack Supports Recursion

Every function call creates a stack frame or activation record on the stack:

  • Return address
  • Arguments
  • Return value
  • Local variables
slide-22
SLIDE 22

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

main

slide-23
SLIDE 23

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

power

x: 2 y: 4 retval:

main

slide-24
SLIDE 24

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

power

x: 2 y: 3 retval:

main power

x: 2 y: 4 retval:

slide-25
SLIDE 25

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

power

x: 2 y: 2 retval:

main power

x: 2 y: 4 retval:

power

x: 2 y: 3 retval:

slide-26
SLIDE 26

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

power

x: 2 y: 1 retval:

main power

x: 2 y: 4 retval:

power

x: 2 y: 3 retval:

power

x: 2 y: 2 retval:

slide-27
SLIDE 27

main

x: 2 y: 0 retval:

power power

x: 2 y: 1 retval:

power

x: 2 y: 4 retval:

power

x: 2 y: 3 retval:

power

x: 2 y: 2 retval:

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

slide-28
SLIDE 28

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

x: 2 y: 0 retval: 1

main power

x: 2 y: 1 retval:

power

x: 2 y: 4 retval:

power

x: 2 y: 3 retval:

power

x: 2 y: 2 retval:

slide-29
SLIDE 29

power

x: 2 y: 1 retval: 2

main

x: 2 y: 0 retval: 1

power

x: 2 y: 4 retval:

power

x: 2 y: 3 retval:

power

x: 2 y: 2 retval:

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

slide-30
SLIDE 30

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

main power

x: 2 y: 1 retval: 2

power

x: 2 y: 4 retval:

power

x: 2 y: 3 retval:

power

x: 2 y: 2 retval:

slide-31
SLIDE 31

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

power

x: 2 y: 2 retval: 4

main power

x: 2 y: 1 retval: 2

power

x: 2 y: 4 retval:

power

x: 2 y: 3 retval:

slide-32
SLIDE 32

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

main power

x: 2 y: 2 retval: 4

power

x: 2 y: 4 retval:

power

x: 2 y: 3 retval:

slide-33
SLIDE 33

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

power

x: 2 y: 3 retval: 8

main power

x: 2 y: 2 retval: 4

power

x: 2 y: 4 retval:

slide-34
SLIDE 34

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

main power

x: 2 y: 3 retval: 8

power

x: 2 y: 4 retval:

slide-35
SLIDE 35

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

power

x: 2 y: 4 retval: 16

main power

x: 2 y: 3 retval: 8

slide-36
SLIDE 36

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

main power

x: 2 y: 4 retval: 16

slide-37
SLIDE 37

An Example

int power(int x, int y) {
 if (y => 0) { return 1; } return x * power(x, n-1); } int main() { printf(“%d\n”, power(2, 4));
 }

main

slide-38
SLIDE 38

Local variables, function arguments are visible (can be accessed) only inside the function. “Normal” local variables and function arguments exist only while the function call is active. static local variables

  • Outlive function call.
  • Have the same memory location in each function call.
  • Stored in the DATA segment of the process’s memory.

Lexical Scopes

char *gentmp() { static char tmp[16]; static int i = 0; sprintf(tmp, “tmp%d.txt”, i); return tmp; }

slide-39
SLIDE 39

Recursion

Recursive functions call themselves. Mutually recursive functions call each other. Each function call has its own stack frame (local variables, ...). Two ways to repeat things:

  • Iteration (or tail-recursion)
  • Recursion (a function can call itself more

than once) int f(../) { ../ if (../) { f(../); } ../ }

int f(../) { ../ if (../) { g(../);
 } ../ } int g(../) { ../ f(../); ../ }

slide-40
SLIDE 40

Example: Computing Fibonacci Numbers

Note: There is an iterative way to do this in linear time. The following recursive solution takes exponential time but matches the formula.

Fn = 1 n = 0 1 n = 1 Fn−1 + Fn−2 n > 1 int fib(int n) { if (n > 1) { return fib(n-1) + fib(n-2); } else { return 1; } }

slide-41
SLIDE 41

Merge Sort

Sorting by Forming
 Longer Sorted Sequences

An inductive approach (recursion can often be viewed as induction):

  • If |A| < 2, then A is sorted
  • Otherwise, we
  • Inductively (recursively)

sort the left and right halves

  • Merge the resulting two

sorted lists Key idea: Reduce sorting to the easier problem of merging two sorted sequences.

void mergesort(int n, int *a) { if (n > 1) { int m = n / 2; mergesort(a, m); mergesort(a + m, n - m); merge(a, m, n); } } Merge Sort recursively Sort recursively 10 8 17 1 13 18 2 1 10 2 18 17 8 13 17 13 8 18 10 2 1 10 8 17 1 13 18 2 Split into half

slide-42
SLIDE 42

Merging

8 13 17 1 2 10 18

slide-43
SLIDE 43

Merging

8 13 17 1 2 10 18

slide-44
SLIDE 44

Merging

8 13 17 2 10 18 1

slide-45
SLIDE 45

Merging

8 13 17 2 10 18 1

slide-46
SLIDE 46

Merging

8 13 17 2 10 18 1

slide-47
SLIDE 47

Merging

8 13 17 10 18 1 2

slide-48
SLIDE 48

Merging

8 13 17 10 18 1 2

slide-49
SLIDE 49

Merging

8 13 17 10 18 1 2

slide-50
SLIDE 50

Merging

13 17 10 18 8 1 2

slide-51
SLIDE 51

Merging

13 17 10 18 8 1 2

slide-52
SLIDE 52

Merging

13 17 10 18 8 1 2

slide-53
SLIDE 53

Merging

13 17 18 8 1 2 10

slide-54
SLIDE 54

Merging

13 17 18 8 1 2 10

slide-55
SLIDE 55

Merging

13 17 8 1 2 10 18

slide-56
SLIDE 56

Merging

17 8 13 1 2 10 18

slide-57
SLIDE 57

Merging

17 8 13 1 2 10 18

slide-58
SLIDE 58

Merging

8 13 1 2 10 18 17

slide-59
SLIDE 59

Merging

8 13 17 1 2 10 18

slide-60
SLIDE 60

Merging

8 13 17 1 2 10 18

slide-61
SLIDE 61

Merging

8 13 17 1 2 10 18

slide-62
SLIDE 62

Merging

8 13 17 1 2 10 18

slide-63
SLIDE 63

Merging

void merge(int *a, int m, int n) { int tmp[n], i, j, k; memcpy(tmp, a, n * sizeof(int)); for (i = 0, j = m, k = 0; i < m &' j < n; +,k) { if (tmp[j] < tmp[i]) { a[k] = tmp[j+,]; } else { a[k] = tmp[i+,]; } } while (i < m) { a[k+,] = tmp[i+,]; } while (j < n) { a[k+,] = tmp[j+,]; } }

slide-64
SLIDE 64

Merge Sort for Arbitrary Element Types

void mergesort(void *a, int elem_size, int n, int (*cmp)(const void *, const void *)) { if (n > 1) { int m = n / 2; mergesort(a, elem_size, m, cmp); mergesort(a + m * elem_size, n - m, cmp); merge(a, elem_size, m, n, cmp); } }

slide-65
SLIDE 65

Merging with Arbitrary Element Types

void merge(void *a, int elsz, int m, int n, int (*cmp)(const void *, const void *)) { char tmp[n * elsz]; int i, j, k; memcpy(tmp, a, n * elsz); for (i = 0, j = m, k = 0; i < m &' j < n; +,k) { if (cmp(tmp + j * elem_size, tmp + i * elem_size) < 0) { memcpy(a + k * elsz, tmp + (j+,) * elsz, elsz); } else { memcpy(a + k * elsz, tmp + (i+,) * elsz, elsz); } } while (i < m) { memcpy(a + (k+,) * elsz, tmp + (i+,) * elsz, elsz); } while (j < n) { memcpy(a + (k+,) * elsz, amp + (j+,) * elsz, elsz); } }

slide-66
SLIDE 66

Running Time of Merge Sort

Merging takes linear time, constant time per element. How many merge steps is each element involved in?
 (Assume n = 2k)

  • Merged sizes: 2, 4, 8, 16, ..., n
  • lg n merge steps

Total running time ~ n lg n Compare: Insertion Sort takes ~ n2 time Practically faster sorting algorithm with n lg n running time in expectation: Quick Sort