http://www.cplusplus.com/reference/cstdlib/realloc/Muy simple. Trata de reservar un bloque de memoria del nuevo tamaño y preserva los datos del bloque anterior.
El retorno es la dirección del nuevo bloque de memoria, así que tienes que guardarlo siempre (igual que haces con malloc). El antiguo bloque, se libera automáticamente, no tienes que hacerlo tú.
Ahora bien, hay 2 casos especiales:
El primero, es que en vez de darte una dirección nueva, te den la misma dirección. Eso significa que simplemente se amplió el tamaño de ese bloque.
El segundo, es que retorne NULL. Eso significa que no se ha podido reservar el bloque que has pedido. El bloque antiguo no e sliberado en este caso, sigue siendo funcional.
Si después del realloc haces free(b), y continuas usando a, pueden pasar varias cosas.
La primera, que b ya no apunte a un bloque de memoria reservado. Esto nunca lo deberías hacer.
La segunda, que a sea NULL, el caso especial. En este caso, tendrás un error.
En caso de que la dirección de los bloques nocambie (el primer caso especial), estarás liberando el bloque, cosa que también será errónea.
En fin, todo esto es supérfluo, y se resume en el segundo párrafo de este mensaje.