Computer systems programming involves developing software to connect the low-level computer hardware to high-level, user-facing application software and usually requires careful consideration of performance and resource constraints. Examples of computer systems software include compilers, operating systems, databases, numerical libraries, and embedded controllers. This course aims to provide a strong foundation in the principles, practices, and art of computer systems programming using C and C++, the languages of choice for system-level programmers. The course will prepare students for more advanced coursework in computer engineering (e.g., embedded systems, computer architecture) as well as more advanced coursework that focuses on a single type of computer systems software (e.g., compilers, operating systems, databases).

The course lectures are structured into three parts. In the first part, students will use C to explore procedural programming (e.g., functions, conditional statements, and iteration statements; recursion; types; pointers; arrays; dynamic allocation); students will then apply their knowledge of C to explore basic algorithms and data structures (e.g., complexity analysis; concrete data types such as lists and vectors; sorting algorithms; abstract data types such as sequences, stacks, queues, sets, and maps). In the second part, students will transition from C to C++ and then use C++ to explore four programming paradigms: object-oriented programming (e.g., C++ classes and inheritance for dynamic polymorphism), generic programming (e.g., C++ templates for static polymorphism), functional programming (e.g., C++ functors and lambdas), and concurrent programming (e.g., C++ threads and atomics); students will then apply their knowledge of multi-paradigm C++ to explore more advanced algorithms and data structures involving trees, tables, and graphs. In the third part, students will explore systems programming in the UNIX environment using the POSIX standard library.

The course includes a series of programming assignments for students to put the principles they have learned into practice. Students will gain experience with UNIX software development including command line development tools, distributed version control, unit testing frameworks, continuous integration, debugging tools, and performance evaluation. In the final programming assignment, students will work in pairs to design, implement, test, and evaluate a high-performance handwriting recognition system which uses machine learning to automatically classify handwritten letters.