C Programming - Pointers

How does free() know how much memory to release?

There's no standard way. It can vary from compiler to compiler, even from version to version of the same compiler. free(), malloc(), calloc(), and realloc() are functions; as long as they all work the same way, they can work any way that works.

Most implementations take advantage of the same trick, though. When malloc() (or one of the other allocation functions) allocates a block of memory, it grabs a little more than it was asked to grab. malloc() doesn't return the address of the beginning of this block. Instead, it returns a pointer a little bit after that.

At the very beginning of the block, before the address returned, malloc() stores some information, such as how big the block is. (If this information gets overwritten, you'll have wild pointer problems when you free the memory.)

There's no guarantee free() works this way. It could use a table of allocated addresses and their lengths. It could store the data at the end of the block (beyond the length requested by the call to malloc()). It could store a pointer rather than a count.

Can math operations be performed on a void pointer?

No. Pointer addition and subtraction are based on advancing the pointer by a number of elements. By definition, if you have a void pointer, you don't know what it's pointing to, so you don't know the size of what it's pointing to.

If you want pointer arithmetic to work on raw addresses, use character pointers.

How do you print an address?

The safest way is to use printf() (or fprintf() or sprintf()) with the %P specification. That prints a void pointer (void*). Different compilers might print a pointer with different formats. Your compiler will pick a format that's right for your environment.

If you have some other kind of pointer (not a void*) and you want to be very safe, cast the pointer to a void*:

printf( "%P\n", (void*) buffer );

There's no guarantee any integer type is big enough to store a pointer. With most compilers, an unsigned long is big enough. The second safest way to print an address (the value of a pointer) is to cast it to an unsigned long, then print that.