Pointer Arithmetic Nuances
Pointer arithmetic in C can be non-intuitive. When you increment a pointer, it actually increases by the size of the type it points to, not by a single byte, enabling direct array traversal without an index variable.
Function Pointers Explained
Function pointers can store addresses of functions, enabling dynamic function calls and callback mechanisms. They are defined with a signature that matches the function, such as `void (*fun_ptr)(int)` for a function taking an int argument.
Pointers to Pointers
Double pointers, or pointers to pointers, allow for dynamic memory allocation of an array of pointers. They are crucial in complex data structures like a dynamically allocated array of strings or implementing a multi-dimensional array.
Void Pointers Flexibility
Void pointers (`void *`) are type-agnostic, allowing them to point to any data type. Before dereferencing, you must cast a void pointer to an appropriate type, which provides flexibility in generic functions or data structures.
Pointers in Structs
Using pointers inside structs can create flexible data structures such as linked lists, trees, and graphs. They enable dynamic memory management and efficient modification of complex structures without copying large amounts of data.
Pointer Type Casting
Casting pointers can change the interpretation of memory content. A common use is with `char *` to inspect individual bytes. However, improper casting leads to undefined behavior, especially if it violates the strict aliasing rule.
Restrict Keyword Usage
The `restrict` keyword, a C99 addition, promises that for the lifetime of the pointer, only it or a derivative will access the object it points to. It helps in optimization by allowing more aggressive compiler assumptions.