I have a hard time understanding how to work with memory pointers. I have two pointers (name, adress, optionalInfo) that points to previously allocated myMemory. Size of these strings can vary. They are stored in myMemory like this:

-------------------------------------------------------------------
| int ID 4Bytes | name 6bytes | adress 8Bytes| optionalInfo 8Bytes|
-------------------------------------------------------------------

Lets say I need to increase or decrease the size of the name and change it. How can I correctly use realloc to not loose any information I want? How can I shift my arguments in memory to free space for a new name? I need to use the least amount of memory.

This is my struct, it is prohibited to change it.

struct myStruct{
    char* name;
    char* adress;
    char* optionalInfo;
    void* myMemory;
};

EDIT: Size of myMemory is known. Name, adress and optionalInfo in this struct are pointers to strings stored in myMemory

1 Answers

0
John Bollinger On Best Solutions

Let's consider the question in terms of this memory layout ...

-------------------------------------------------------------------
| int ID 4Bytes | name 6bytes | adress 8Bytes| optionalInfo 8Bytes|
-------------------------------------------------------------------

... ignoring how it may relate to members of struct myStruct other than myMemory.

Lets say I need to increase or decrease the size of the name and change it. How can I correctly use realloc to not loose any information I want?

As long as you realloc to a size at least as large as the data already occupy, no data will be lost by the reallocation. Nor will any be moved relative to the start address of the block. Note, however, that the reallocated block may be in a different location than the original one, and if it is, then the original block will have been freed, and must not be accessed any longer.

How can I shift my arguments in memory to free space for a new name?

The most obvious tool for that job would be the memmove() function. So, supposing that you want to increase the size of the region labelled "name" from 6 bytes to, say, 10 bytes, without overwriting any of the other data, you first need to reallocate:

void *temp = realloc(x.myMemory, old_size + 4);

Since realloc() is not guaranteed to succeed, you must not update the x.myMemory pointer until you very that it did succeed:

if (temp) {  // if temp is non-null

You can then shift the address and optionalInfo data within the larger space to make room for more name info:

    memmove(((char *)temp) + new_offset_of_address_data,
            ((char *)temp) + old_offset_of_address_data,
            combined_size_of_address_and_optionalInfo_data);

The casts to type char * are needed because pointer arithmetic is defined in terms of units of the pointed-to type, and therefore is not defined at all for pointers to void.

Do not forget to assign the new pointer to your structure:

    x.myMemory = temp;
}