C Caveats

I needed to dabble in C again, and of course I had forgotten almost everything about it...

Pointers

int *np;       // np is a pointer to an int. Read: "*np is of type int". 
*np = 3;       // Errror! You are dereferencing an unitialized pointer. 
               // The address stored in np is most likely garbage.
int num = 3;   // Now there is actually something we can point to.
np = &num      // Makes np point to num.
*np = 4        // * dereferences the pointer, so that you can write/read what
               // it is pointing to. Both num and *np now "are" 4.
np             // this is just the value of the pointer, i.e. an adress
np+1           // Points to the next element. Depending on architecture and
               // typeof(*np), the actual address may be bigger by 1,2,4,...
*np++          // Note the precedence: it is *(np++), meaning: give me the
               // value stored at np, and incr. the pointer. 

Null vs. Void

int *np = NULL; // NULL is a preprocessor macro that makes the
                // pointer point to "nothing interesting", "something safe."
void *np2;      // Declares a generic pointer. Points to "void", which is
                // a type, just like int and float, only it's always empty.
                // A void pointer is a "promiscuous" pointer. Use it if you
                // can't say what it will end up pointing to. This, on purpose, 
                // circumvents the strict static typing of C. 

Static vs. Const

const int a = 3; // a is a variable (with allocated memory!) that is not allowed
                 // to change. You can still change it via pointers. Don't. 
# define a 3     // The symbol "a" is replaced by the symbol "3" by the 
                 // preprocessor. It (probably) won't take up memory.
const int *ap;   // ap is a pointer to a const int. Often used when pointers are
                 // passed to functions, and the functions are not allowed to
                 // change the content that the pointers point to.
int * const ap;  // ap is a "constant pointer", meaning the pointer must not
                 // change. You can change what it points to, though. Array
                 // names are like this. (?)
int arr[10];     // somewhat comparable to int * const arr. (?)
static int a = 3 // If in a function: Compiler "initializes" it and let's the
                 // function have access to it. Value is "remembered" through
                 // multiple function calls.
static void fun(void) {..} 
                 // Caution: Meaning is different now, outside function: fun
                 // is only "visible" from the same (object) file.

Declare vs. Define vs. Initialize

extern int a; // Declaration: Tell compiler about a thing "int a". This thing
              // is defined somewhere else, though, so don't reserve memory.
int b;        // Declaration + (tentative) definition: Compiler reserves
              // memory. Tentative: If there is another, agreeing one, it's ok.
int b;        // Legal because "tentative definition".
float b;      // error
int b = 3;    // Declaration, definition and initialization in one statement.
              // Memory is reserved and filled with meaningful stuff.