We don’t want to write the same thing many times; generics minimizes code duplication. Therefore, generics! Let’s implement a simple swap function: void swap_ptr_values(void *data1ptr, void *data2ptr, size_t datasize) { } helper functions memcpy Copy datasize bytes worth of memory in the second argument into the first argument. The two arguments CANNOT OVERLAP otherwise, you risk UB. void *memcpy(void *dest, void *src, size_t nbytes) memmove Its memcpy, but it works with overlapping data, and is slower. void *memove(void *dest, void *src, size_t nbytes) pointer arithmetic with generics Unfortunately, given that we don’t know how big a void * pointer is, we can’t do pointer arithmetic against it because it still doesn’t know how big the pointer is. You can’t just add/subtract numbers to char . So, we actually have to do pointer arithmetic by casting the pointer to a char which will make pointer arithmetic work at the one-byte level. void *return_sixth_elem(void *arr) { return (char *)arr + 5; } higher order functions We can pass a function as a parameter. bool (*function_name)(int, int)