Announcements CSCI 334: Principles of Programming Languages Lab 1 due Sunday by 11:59pm No class Friday (Winter Carnival) Lecture 2 No class Tuesday (PC meeting) Instructor: Dan Barowy Outline technical communication low-level big questions knowledge (C) high-level 1. Quiz (theoretical) knowledge LISP & functional 2. LeWitt assignment MIDTERM programming language 3. Boxes and arrows model architecture F# object orientation (C++)
C C Read the “Intro” doc. Some useful “functions” for Lab 1 malloc atoi free printf sizeof strncpy memset fscanf C rand fopen Not a function; no man page srand fclose Read the “Intro” doc. rewind If you haven’t started, start now. See the “man” pages
sizeof operator “man” pages sizeof is a compile-time unary operator which computes the size of its operand in bytes . The result of sizeof is of unsigned integral type ( size_t ). sizeof can take two kinds of operands: 1. a data type (e.g., int , float , etc.), or 2. an expression (e.g., 2 + 1.07 ). Manual memory management • C was invented in 1972. C is about memory • It features manual memory management . • Automatic memory management was invented in 1959! It uses a model of a computer that I call the • So… why have manual “ boxes and arrows model .” management? • In C, manual memory management is a feature , and it’s the Ken Thompson (inventor of C, sitting) and reason why it might be Dennis Ritchie (inventor of UNIX, standing). your language of choice. • OS, high-performance code, etc.
#include <stdio.h> #include <stdio.h> void hello() { void hello() { printf(“Hello world!\n”); printf(“Hello world!\n”); } } int main() { int main() { hello(); hello(); return 0; return 0; } } Call stack Call stack #include <stdio.h> #include <stdio.h> void hello() { void hello() { printf(“Hello world!\n”); printf(“Hello world!\n”); } } int main() { int main() { main hello(); main hello(); return 0; return 0; } } Call stack Call stack
printf printf #include <stdio.h> #include <stdio.h> void hello() { void hello() { printf(“Hello world!\n”); printf(“Hello world!\n”); hello hello } } int main() { int main() { hello(); hello(); main main return 0; return 0; } } Call stack Call stack #include <stdio.h> #include <stdio.h> void hello() { void hello() { printf(“Hello world!\n”); printf(“Hello world!\n”); hello } } int main() { int main() { main hello(); main hello(); return 0; return 0; } } Call stack Call stack
Why do we need pointers? program is done #include <stdio.h> void hello() { printf(“Hello world!\n”); } int main() { hello(); 1. “Any problem in computer science can be solved return 0; } with another level of indirection.” —Butler Lampson Call stack 2. They are necessary for building “persistent” data structures. Storage Duration Storage Duration: Automatic int i = 3; We will focus on two: automatic and allocated i has automatic duration, because you didn’t specify anything. You (the programmer) choose which one you want . C will automatically acquire ( allocate ) Rule: and release ( deallocate ) memory for this variable. Always choose automatic duration unless the lifetime of your data outlives its allocation site, in which case, you should choose allocated duration . In reality, nearly every C implementation will store i on the call stack .
Storage Duration: Automatic Storage Duration: Automatic #include <stdio.h> #include <stdio.h> int main() { int main() { int i = 3; int i = 3; return i; return i; i i ← 3 } } main main Call stack Call stack Storage Duration: Automatic Storage Duration: Automatic #include <stdio.h> #include <stdio.h> int main() { int main() { int i = 3; int i = 3; return i; return i; } } Call stack Call stack main ’s stack frame and all variables in it (i.e., i ) are Where does i get returned? How? automatically deallocated when main goes out of scope .
Activity Storage Duration: Allocated int *i = malloc(sizeof(int)); #include <stdio.h> int add(int x, int y) { int z = x + y; 2 return z; i has allocated duration, because you used malloc . } int main() { C will manually allocate on request 1 int x = 1; and deallocate memory on request . int z = add(x, 3); 3 return z; } In reality, nearly every C implementation will store i on the heap . Diagram the stack and variables when the program is at the three points. Storage Duration: Allocated Storage Duration: Allocated T o deallocate, you must call free int *i = malloc(sizeof(int)); #include <stdio.h> free(i); #include <stdlib.h> int foo() { You have to do this even if i goes out of scope! int i* = malloc(sizeof(int)); *i = 3; i foo return 0; } Failing to free when you are done is a bug called a memory leak . main Call stack
Storage Duration: Allocated Storage Duration: Allocated 3 #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <stdlib.h> int foo() { int foo() { int i* = malloc(sizeof(int)); int i* = malloc(sizeof(int)); *i = 3; *i = 3; i i return 0; return 0; foo foo } } main main Call stack Call stack Storage Duration: Allocated Storage Duration: Allocated 3 3 #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <stdlib.h> int foo() { int foo() { int i* = malloc(sizeof(int)); int i* = malloc(sizeof(int)); *i = 3; *i = 3; i foo return 0; return 0; } } Anyone see a problem? Anyone see a problem? main main 3 is now unreachable, and we cannot reclaim it. Memory leak. Call stack Call stack
Activity #include <stdio.h> void add(int *x, int *y, int *z) { *z = *x + *y; Call-by-value 2 } int main() { (program evaluation strategy) int x = 1; int y = 3; 1 int z; add(&x, &y, &z); Examples: 3 return z; } C Diagram the stack and variables when the program is at the three points. Java Python Call-by-value #include <stdio.h> int add(int x, int y) { int z = x + y; return z; } #include <stdio.h> int main() { int x = 1; int add(int x, int y) { int z = add(x, 3); int z = x + y; return z; return z; } } int main() { int x = 1; How does a function “obtain” a parameter value? int z = add(x, 3); return z; Call stack } Call-by-value semantics: copying
Call-by-value Call-by-value #include <stdio.h> #include <stdio.h> int add(int x, int y) { int add(int x, int y) { int z = x + y; int z = x + y; return z; return z; } } int main() { int main() { x x = 1 int x = 1; int x = 1; main main z z int z = add(x, 3); int z = add(x, 3); return z; return z; Call stack } Call stack } Call-by-value Call-by-value Not the same x ! #include <stdio.h> #include <stdio.h> int add(int x, int y) { int add(int x, int y) { int z = x + y; int z = x + y; x = 1 return z; return z; add y = 3 } } z int main() { int main() { x = 1 x = 1 main int x = 1; main int x = 1; z z int z = add(x, 3); int z = add(x, 3); return z; return z; Call stack } Call stack }
Call-by-value Call-by-value Not the same z ! #include <stdio.h> #include <stdio.h> int add(int x, int y) { int add(int x, int y) { int z = x + y; int z = x + y; x = 1 return z; return z; add y = 3 } } z = 4 int main() { int main() { x = 1 x = 1 int x = 1; int x = 1; main main z z = 4 int z = add(x, 3); int z = add(x, 3); return z; return z; Call stack } Call stack } What can a function return? What can a function return?
Recap & Next Class C String Trick Today we covered: Ensuring null termination is not always easy. Boxes and arrows model memset can make reasoning about C strings easier. char *memset(char *buf, char c, size_t len) Next class: e.g., memset(&dst,’\0’,sizeof(dst)) Going deep with pointers Assuming that dst is an automatic buffer. Final projects
Recommend
More recommend