CS 136 - 3 - C Model

3.1 - Control Flow

Models of computation

Control Flow

Types of control flow

Looping

while (expression) statement
// this is our first loop program

#include "cs136.h"

int main(void) {
  int i = 2;
  while (i >= 0) {
    printf("%d\n", i);
    --i;
  }
}

Produces:

2
1
0

Iteration vs. recursion

// this program demonstrates the conversion between simple recursion and 
//   iteration

#include "cs136.h"

// recursive_sum(k) finds the sum of the numbers 0...k using simple recursion
int recursive_sum(int k) {
  if (k <= 0) {
  	return 0;
  }
  return k + recursive_sum(k - 1);
}

// iterative_sum(k) finds the sum of the numbers 0...k
int iterative_sum(int k) {
  int s = 0;
  while (k > 0) {
  	s += k;
    --k;
  }
  return s;
}

int main(void) {
  trace_int(recursive_sum(5));
  trace_int(iterative_sum(5));
}

Produces:

>>> [main.c|main|25] >> recursive_sum(5) => 15
>>> [main.c|main|26] >> iterative_sum(5) => 15

You can also nest loops!
Example:

// this is our first "nested" loop

#include "cs136.h"

int main(void) {
  int i = 5;
  while (i >= 0) {
    int j = i;
    while (j >= 0) {
      printf("*");
      --j;
    }
    printf("\n");
    --i;
  }
}

Produces:

******
*****
****
***
**
*

Tracing tools

do ... while

Syntax for a do ... while loop:

do statement while (expression);

break

continue

Example for break and continue:

// this program demonstrates the use of the break statement

#include "cs136.h"

// odd(n) returns true if a number is odd and false otherwise
bool odd(n) {
  return (n % 2 != 0);
}

int main(void) {
  int n = 0;
  while (1) {
    if (1 != scanf("%d",&n)) {
      break;
    }
    if (!odd(n)) {
      continue;
    }
    printf("%d\n", n);
  }
}

for loops

for (setup; expression; update) { 
   body statement(s) 
}
for (i = 1, j = 100; i < j; ++i, --j) {...}

3.2 - Memory and Variables

Memory

Defining Variables

sizeof

// this program demonstrates the sizeof an int

#include "cs136.h"

int main(void) {
  int n = 0;
  trace_int(sizeof(int));
  trace_int(sizeof(n));
}

Produces the output:

>>> [main.c|main|7] >> sizeof(int) => 4
>>> [main.c|main|8] >> sizeof(n) => 4

Integer limits

Overflow

The char type

ASCII

C Characters

// this program shows that 'a' and 97 are equivalent

#include "cs136.h"

int main(void) {

  char letter_a = 'a';
  char ninety_seven = 97;

  printf("letter_a as a character:   %c\n", letter_a);
  printf("ninety_seven as a char:    %c\n", ninety_seven);  

  printf("letter_a in decimal:       %d\n", letter_a);
  printf("ninety_seven in decimal:   %d\n", ninety_seven);

}

Produces:

letter_a as a character:   a
ninety_seven as a char:    a
letter_a in decimal:       97
ninety_seven in decimal:   97

Character arithmetic

Reading characters from input

// this program reads in characters and prints them out,
// while converting to lowercase

#include "cs136.h"

// is_lowercase(c) returns true if c is lowercase and false otherwise
bool is_lowercase(char c) {
  return (c >= 'a') && (c <= 'z');
}

// to_lowercase(c) converts upper case letters to
//   lowercase letters, everything else is unchanged
char to_lowercase(char c) {
  if ((c >= 'A') && (c <= 'Z')) {
    return c - 'A' + 'a';
  } else {
    return c;
  }
}

int main(void) {
  while (1) {
    char c = 0;
    int retval = scanf("%c",&c);
    if (retval != 1) {
      break;
    }
    if (!is_lowercase(c)) {
      printf("%c", to_lowercase(c));
    } else {
      printf("%c", c);
    }
  }
}

Stdin:

SdfV3J; kla;LsASDFNC
dfF \n aAsklDjdEfK8 3

Produced Output:

sdfv3j; kla;lsasdfnc
dff \n aaskldjdefk8 3

Whitespace and reading characters

Symbol type

3.3 - Memory - Structures

Structures

// Usual initialization:
struct posn {       // name of the structure
  int x;            // type and field names
  int y;
};                  // don't forget this ;

// You would then use it like such:
int main(void) {
  struct posn p = {1, 2};
  
  trace_int(p.x);
  trace_int(p.y);  
}

// Can initialize as such:
struct posn p = { .y = 4, .x = 3};

// any omitted fields are automatically zero, which can be useful! Like so:
struct posn p = {.x = 3}; // .y = 0

Mutation with structures

Structures in the memory model

sizeof a struct

3.4 - Memory - Sections

Sections of memory

CODE
READ-ONLY DATA
GLOBAL DATA
HEAP
STACK

The code section

The read-only & global data sections

3.5 - Memory - Stacks and Recursion in C

Function Calls (revisited)

Stacks

The Call stack

The return address

Stack frames

Recursion in C

Stack section

The call stack is stored in the stack section, the fifth section of our memory model. We refer to this section as “the stack”.

Uninitialized memory

Always initialize variables!