Search code examples
cmallocrealloc

Initialize array of pointers to NULL with realloc without iteration


Is it possible to automatically initialize to NULL the pointers inside an array reallocated with realloc without iterate over it? I would like to do something like calloc but i need te resize an already existent block of memory.

For example:

#DEFINE N  50
typedef int *pointerToInt;
typedef pointerToInt *pointerToPointer;
int main(){
   pointerToInt p;
   pointerToPointer pp;
   pp = malloc(sizeof(p)*N);
   //Now i want to resize and initialize my resized vector
   pp = realloc(pp, sizeof(p)*(N+10));
}

In first approximation I could change the mallocto calloc, but when I use realloc there's nothing that guarantees me initialized pointers.

Is it necessary to iterate over the whole array and set each single pointer to NULL? Or there's a better way using only callocand realloc?


Solution

  • The short answer is: No, there is no standard function to reallocate a block of memory and initialize its newly allocated portion to all bits zero.

    The solution is either:

    • to not require initialization by keeping track of the valid portion of the array. You obviously must have a way to do this, otherwise how would you decide to reallocate the object.
    • to initialize the newly allocated portion explicitly.

    There are several problems in your code:

    • #DEFINE N = 50 is incorrect, it should just be #define N 50
    • hiding pointers behind typedefs is bad: it makes the code obscure and error prone. To do it twice is evil.
    • you did not include <stdlib.h>
    • you do not test for malloc failure
    • you do not initialize the array allocated by malloc() either.

    Here is a modified version:

    #include <stdlib.h>
    
    #define N 50
    
    int main(void) {
        int i;
        int **pp, **pp1;
        pp = malloc(sizeof(*pp) * N);
        if (pp) {
            for (i = 0; i < N; i++) {
                pp[i] = NULL;
            }
            //Now I want to resize and initialize my resized vector
            pp1 = realloc(pp, sizeof(*pp) * (N + 10));
            if (pp1) { 
                pp = pp1;
                for (i = N; i < N + 10; i++) {
                    pp[i] = NULL;
                }
            }
            free(pp);
        }
        return 0;
    }
    

    Note that you could write a utility function for your purpose:

    #include <stdlib.h>
    #include <string.h>
    
    void *realloc_zero(void *p, size_t size, size_t new_count, size_t count, int *err) {
        void *newp;
        if (p == NULL)
            count = 0;
        newp = realloc(p, size * new_count);
        if (newp == NULL) {
            *err = 1;
            return p;
        } else {
            if (new_count > count) {
                memset((unsigned char*)newp + size * count, 0, size * (new_count - count));
            }
            *err = 0;
            return newp;
        }
    }
    
    #define N 50
    
    int main(void) {
        int err;
        int **pp;
        pp = calloc(sizeof(*pp), N);
        ...
        //Now I want to resize and initialize my resized vector
        pp = realloc_zero(pp, sizeof(*pp), N + 10, N, &err);
        if (err) {
            // could not resize
            free(pp);
            return 1;
        }
        ...
        free(pp);
        return 0;
    }
    

    Note however that both calloc and realloc_zero initialize the block to all bits zero, which is not guaranteed by the C Standard to be a proper representation of NULL, although most current architectures do represent the null pointer this way.