سؤال

In this example from: http://www.cplusplus.com/reference/cstdlib/realloc/ why are there two pointers: numbers and more_numbers? Can I use:

numbers = (int*) realloc (numbers, count * sizeof(int));
if (numbers!=NULL) {
       numbers[count-1]=input;
}
else {
       free (numbers);
       puts ("Error (re)allocating memory");
       exit (1);
}
هل كانت مفيدة؟

المحلول 2

To see why your version is wrong, you need to realise what realloc does. It does one of two things: If there is enough memory, it will return a new pointer and the old one becomes invalid. If there isn't enough memory, it will return NULL and the old pointer stays valid and unchanged.

You must store the result of realloc into a temporary variable, and not overwrite the old pointer. The reason is that if realloc returns NULL, and you overwrote the old pointer with NULL, you lost access to your existing data. So the correct way is:

int* tmp = (int*) realloc (numbers, count * sizeof(int));
if (tmp!=NULL) {
    // realloc was successful. The old value of numbers is now rubbish. 
    // Store the result of realloc into numbers and continue. 
    numbers = tmp; 
    numbers[count-1]=input;
}
else {
    // realloc failed. The old value of numbers is unchanged but doesn't have enough
    // space to store input. You need to handle the error somehow. 
    free (numbers);
    puts ("Error (re)allocating memory");
    exit (1);
}

If you had stored the realloc () result directly into numbers, the "else" branch wouldn't know the old value of numbers anymore and couldn't free that memory.

نصائح أخرى

The reason that example appears a little extended is to adequately deal with a failure to realloc.

numbers = (int*) realloc (numbers, count * sizeof(int));
if (numbers!=NULL) {
       numbers[count-1]=input;
}
else {
       free (numbers);

This will not work in the error condition; you'll be trying to free a value which you just confirmed is NULL, which probably isn't what you intend. Additionally, you've lost the (still valid) original pointer in this case (the purpose of the more_numbers pointer in your example), losing access to the data you have there and losing the ability to release the buffer.

According to link http://www.cplusplus.com/reference/cstdlib/realloc/

it is written "The program prompts the user for numbers until a zero character is entered. Each time a new value is introduced the memory block pointed by numbers is increased by the size of an int."

have a look at the function realloc() in http://www.tutorialspoint.com/c_standard_library/c_function_realloc.htm

void *realloc(void *ptr, size_t size);

The function returns a pointer to the newly allocated memory, or NULL if the request fails.

ptr -- This is the pointer to a memory block previously allocated with malloc, calloc or realloc to be reallocated.If this is NULL, a new block is allocated and a pointer to it is returned by the function

size -- This is the new size for the memory block, in bytes.If it is 0 and ptr points to an existing block of memory, the memory block pointed by ptr is de-allocated and a NULL pointer is returned

So after allocating memory this function returns a void pointer and it is type-casted to an integer pointer to use in the code. So each time a code is entered the memory allocated will be incremented 1 times by the sizeof(int) and the value is stored in that area.

more_numbers is the pointer which points to the starting address of the location of the memory allocated by the realloc()

numbers is the pointer which points to the array where the inputs are stored

In case if the memory allocation fails the entire memory is de-allocated using free();

You could use a function (hope i did this right):

/// int*-argument passed by-pointer
bool Enlarge(int** input, size_t new_count, int new_val)
{
    void* numbers = NULL;  // local ptr

    numbers = (int*) realloc (*input, new_count*sizeof(int));
    if (numbers!=NULL) {

      *input = (int*)numbers;
      (*input)[new_count - 1] = new_val;

      return true;
    } else {
      return false;
    }
}

Use it:

int* old = (int*)malloc(sizeof(int)*2);
if (!old)
    return -1;
old[0] = 11; old[1] = 22;
if (!Enlarge(&old,3,33))
{
    free(old);
    return -2;
}
printf("A: %d, B: %d, C: %d\n", old[0], old[1], old[2]);
if (old) {  free(old);  }

Just beware to pass the ptr as int** and not as int* (e.g. when specifying &old[0] instead of &old.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top