Course SP General Sheet

Abstract:

Systems programming is the activity of writing computer system software: used as a platform for other software, a layer of abstraction (scaffolding) i.e. the main ‘customer’ is other software, not necessarily users. Usually, system software has particular performance constraints such as: fast execution time, low memory consumption, low energy usage Because of this these languages allow for a more fine grained control over the execution of programs

Types of System Programming:

  • Operating Systems
  • Drivers
  • Compilers

Core Concepts

Stack and Heap

When the lifetime of an automatically managed variable ends, its memory location is freed and can be reused by other variables

This memory management happens fully automatically as it is very easy to implement:

  • every time a block is entered, put aside a location in memory for every variable declared in the block
  • every time a block is exited, free the locations in memory for every variable declared in the block As this memory management strategy adds and removes memory locations in a last-in-first-out manner we call this stack-based memory management and the area of memory managed in this way the stack

The Heap which is managed manually by the programmer

Stack

Heap

Datatype Sizes

Type (Signed/Unsigned)Typical Byte SizeValue Range
char1[-127, +127] / [0,255]
short2[-32767, +32767] / [0,65535]
int4[-2147483647, +2147483647] / [0, 4294967295]
long4/8at least as for int
long long8[-2^{63}-1, +2^{63}+1] / [0, 2^{64}-1]

Lexical Scoping

Each pair of brace: { } , is called a block in C and introduces a lexical scope. variable names must be unique in the same lexical scope. If multiple are defined, then the innermost blocks variable is used

Lifetime of Variables

Variables are stored at locations in memory that do not change over their lifetimes

There are three cases:

automatic

These are all variables declared locally in a block (i.e. inside a pair of {}) and their lifetime ends at the end of the block. All variables we have seen so far fall into this category.

int main() { int x = 42; } // end of the block - end of the lifetime of x

static:

Variables declared with the static keyword or defined at file-level outside all blocks. The lifetime is the entire execution of the program.

int foo() {
static int count_calls_to_foo = 0; // the variable is initialized only once count_calls_to_foo++; 
} // variable continues to live

allocated:

These are variables for which we must explicitly request memory using dynamic memory allocation functions (such as malloc). We manage the lifetime of these variables ourselves (next lecture!).

Multi Element Types

Struct

A struct consists of a sequence of members of (potentially) different types:

struct point { int x; int y; };
int main() {
	struct point p = {1, 2};
	printf("x = %d\ny = %d\n", p.x, p.y);
}

Members are accessed like public class members in Java using the . notation Members are stored next to each other in memory in the same order as defined in the struct The type of a struct is written struct name, but we often use this trick to shorten it:

typedef struct { int x; int y; } point;
int main() { point p = {1, 2}; /* ... */ }
String

Strings in C are represented as arrays of characters

char greeting[] = "Hello World";

is the same as

char greeting[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '\0'};

We use double quotes ” to write a (ASCII) string literal and single quotes ’ to write a character literal

Strings in C are terminated by the special character '\0' that is added automatically for string literals

To print a string with printf we use the %s formation character

printf("%s\n", greeting);

If we forget the terminating '\0' character this will print the content of the memory until it hits the next bit pattern equivalent of '\0'!

Functions

Definition

Functions are probably the most important abstraction mechanism in computing science They allow us to write code in a modular fashion which we can then reuse

A function definition in C looks like this:

int max(int lhs, int rhs) {
	if (lhs > rhs) { return lhs; } else { return rhs; } 
}

The return type specifies the data type of the value that will be returned after evaluating the function. If a function returns no value the special type void is used as return type

The name which should describe the behaviour of the function

A parameter list specifies the data type and name of each parameter expected by the function

The function body is a block containing the code executed when calling the function

To call a function we provide an argument for each parameter and capture/process the return value

int x = max(5, 3);

Declaration

Instead of defining the full function, this only specifies the interface of how a function can be used

int max(int lhs, int rhs);

This is important as this is what the Compiler looks at when it checks that the call being made is valid. The linker then searches for the definition, which can be in a different file