I'm currently trying to design a public API for a queue data structure and resize function to change its size. My first intention was to do it in the following way:
typedef struct queue queue;
/**
* Resizes a given queue.
*
* Changes the size of the queue passed as a parameter.
* The content of the resized queue prior to the lesser
* of new and old sizes is left unchanged.
*
* Returns:
* 0 - on success
* -1 - on error and the content of the original queue is left unchanged
*/
int queue_resize(queue * queue_ptr, size_t new_size);
The problem is I read the contract to realloc
and it was the following:
The
realloc
function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.
Is it a common approach for reallocation functions to return a new object and reclaim the old one? So in such a case I should have redesigned the int queue_resize(queue *queue_ptr, size_t);
to make queue * queue_resize(queue *queue_ptr, size_t);
with the corresponding contract changes.
realloc
must be able to move the allocated space to a different address for it to be able to work. Imagine the memory directly after the currently allocated memory was already in use. Without relocation you could not create a contiguous sequence.
Typically your queue will look something like this
typedef struct queue {
some_type* data_member;
size_t size;
size_t capacity;
// .. perhaps more
} queue;
So when you have a queue_resize
function you can just pass a queue*
and the new size. What you pass to realloc
is not the queue*
but its data_member
. Since you already have a pointer to the queue
object, you can just update the pointer of data_member
if realloc
chooses to change it.
In this case returning a new queue*
object is not necessary, because the memory footprint of queue
never changes. Nor do you have to pass a queue**
or anything of the sort.