Please read this page about taking my exams!

Exam format


Things people asked about in the reviews

This is a list of what people asked about. The exam may have other topics not listed, and some of these topics may not appear on the exam.

Pointers

example:

int x = 10;
int y = 20;
int p = &x; // p points to x
//   ________
// x |  10  |<--+
//   |------|   |
// y |  20  |   |
//   |------|   |
// p |    --|---+
//   |------|
printf("%d\n", *p); // "print the value-at p" - prints 10, cause that's what p points to
p = &y; // changes where p points; now it points to y
//   ________
// x |  10  |
//   |------|
// y |  20  |<--+
//   |------|   |
// p |    --|---+
//   |------|
(*p)++; // increments the value that p points to; increments y to 21
//   ________
// x |  10  |
//   |------|
// y |  21  |<--+
//   |------|   |
// p |    --|---+
//   |------|
printf("%d\n", y); // prints 21

Undefined Behavior (UB)

Pointer arithmetic (you should def know this)

Passing arguments by value versus by reference

void my_function(int x) { // passing by VALUE (or "by COPY")
	// this x is different from the x in main.
	// modifying it only affects this variable, not main's.
    x = 10;
    printf("%d\n", x); // prints 10
}

int main() {
    int x = 20;
    my_function(x); // this *copies* the value 20 into my_function.
    printf("%d\n", x); // prints 20
    return 0;
}
void my_function(int* p) { // passing by REFERENCE
    *p = 10; // dereferencing - changes main's x!
    printf("%d\n", *p); // prints 10
}

int main() {
    int x = 20;
    my_function(&x); // &T ==> T*
    printf("%d\n", x); // prints 10!
    return 0;
}

Returning pointers to locals (why it’s bad)

int* my_function() {
    int x = 500;
    // have to do this to trick gcc into compiling
    int* p = &x;
    return p;
}

void another_function() {
    // ooh it has variables
    int a = 10, b = 20, c = 30;
}

int main() {
    int* p = my_function();
    // at this point, p points to a region of the stack
    // that is BELOW the sp. if you printed out *p now,
    // it would *likely* print out 500, but you are not
    // guaranteed *anything* about the validity of doing
    // it; it is UB.

    // if we then call another function...
    another_function()

    // ...now we have *no* idea what this will print,
    // because another_function reused the stack space
    // that p is pointing to.
    printf("%d\n", *p);
    return 0;
}

Struct padding

typedef struct {
    int x;    // 4 bytes
    char c;   // 1 byte
    double d; // 8 bytes
} MyStruct;

// if we print out sizeof(MyStruct) you might expect it to be 13, but it's actually 16.

enum

typedef enum {
	// by default, enum values are integers starting at 0 and increasing.
	// so A == 0, B == 1, C == 2
	// but you can set them to whatever you want, by writing:
	// 	A = 5, B = -17, C = 494
    A, B, C
} E; // E is now a typedef for whatever underlying integer type the compiler chose for this enum

int main(int argc, char const *argv[])
{
    E e = A; // there is no namespace, you don't write E.A, just A
    e = B;
    e = C;

    // the compiler doesn't prevent you from doing this, but it's not good.
    // on gcc, E is given an unsigned type, and this line actually puts 4294967295
    // into e!
    e = -1;

    return 0;
}

Using the heap in C

The heap allocator and how it works

Scope, Lifetime, Ownership