-1

Can we dynamically allocate memory for structures? Is this a correct procedure to approach a dynamically allocated structures? Please tell me how to malloc() and realloc() a structure.

newnode is of type struct List * but when start indexing it converts to struct List.How this conversion possible?My insert function accepts only (struct List*) Am I wrong somewhere?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct List {
    char val[20];
};

void insert(struct List *);

int main(void) {
    int i = 0;
    int size = 1;
    struct List *newnode = (struct List *)malloc(size * sizeof(struct List));
    for (i = 0; i < 5; i++) {
        if (size <= i) {
            size = size + size;
            newnode = (struct List *)realloc(newnode, size * sizeof(struct List));
        }
        scanf("%s", newnode[i].val);
        insert(newnode[i]);
    }
    for (i = 0; i < 5; i++) {
        printf("%s\n", newnode[i].val);
    }
    return 0;
}

void insert(struct List *node) {
    printf("%s\n", node->val);
}

2 Answers2

1

The code works except for 3 problems:

  • You do not test for memory allocation failure. Both malloc() and realloc() will return NULL if memory cannot be allocated: you will get undefined behavior when dereferencing newnode should this happen.

  • to handle the case of realloc() failure gracefully, you should store the reallocated pointer to a different variable so you can still access the previous array that has not been deallocated and free it.

  • scanf("%s", newnode[i].val); is a security flaw: you should limit the number of bytes that can be stored to the destination array with

    scanf("%19s", newnode[i].val);
    
  • you do not test the return value of scanf() to detect invalid or missing input.

  • insert() does not insert anything.

Here is a modified version with error handling and less confusing names:

#include <stdio.h>
#include <stdlib.h>

struct Item {
    char val[20];
};

//void insert(struct Item *);

int main(void) {
    int i, j;
    int size = 0;
    struct Item *array = NULL;
    for (i = 0; i < 5; i++) {
        if (i >= size) {
            int newsize = size ? 1 : size + size;
            struct Item *newarray = realloc(array, sizeof(*array) * size);
            if (newarray == NULL) {
                perror("cannot reallocate the array");
                break;
            }
            size = newsize;
            array = newarray;
        }
        if (scanf("%19s", array[i].val) != 1) {
            fprintf(stderr, "missing input\n");
            break;
        }
        //insert(array[i]);
    }
    for (j = 0; j < i; i++) {
        printf("%s\n", array[i].val);
    }
    free(array);
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
-1

Yes, this is fine except that you are assigning the return value to your original array pointer. realloc() returns NULL if it can't resize the memory. You need to assign it to a temporary variable and, if the value is NULL, don't overwrite a.

The main thing you have to watch out for are pointers, which your struct doesn't have. In those cases, the memory pointed to is not part of the allocated array.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466