1

I am writing a program that needs to create a variable number of linked lists. The following is declared globally at the beginning of the program:

struct Node
{
    int Line;
    struct Node *Next;
} ;

struct Node* Heads[5];
struct Node* Currs[5]; 

int NumOfNames;

The first function in main() will calculate and store a value for NumOfNames. I then need the size of Heads[5] and Currs[5] to be changed to Heads[NumOfNames] and Currs[NumOfNames] in order to create NumOfNames amount of linked lists. Can anything along these lines be done?

I am quite new to programming and my knowledge of malloc and realloc is very poor, but I think I somehow need to use these functions in order to achieve my goal.

Thank you for any advice in advance.

KOB
  • 4,084
  • 9
  • 44
  • 88
  • 2
    You cannot have globally declared arrays with variable length. Therefore you definitely need to use `malloc` and friends. – Jabberwocky May 05 '15 at 12:03
  • @MichaelWalz So if I understand correctly, when I globally declare `Heads` and `Currs`, memory is being allocated to them. Then, once `NumOfNames` has been calcluated I need to use `realloc` in order to reallocate enough memory for each of the arrays to be of size `NumOfNames`? – KOB May 05 '15 at 12:06
  • `Heads` is an array, not a pointer. You cannot invoke `realloc` on an array. – William Pursell May 05 '15 at 12:09

4 Answers4

3

You need this:

struct Node
{
    int Line;
    struct Node *Next;
} ;

struct Node** Heads;
struct Node** Currs; 
int NumOfNames ;

main()
{
  int NumOfNames = ... ; // calculate the number of names
  ...
  Heads = malloc(NumOfNames * sizeof (struct Node*));
  // now Heads point to an array of pointers to struct Node of length NumOfNames
  ...
  Heads[1] = malloc(sizeof (struct Node));
  ...
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
2

Stop using static arrays, and allocate at runtime instead:

struct Node* Heads;
struct Node* Currs; 

Heads = malloc(NumOfNames * sizeof *Heads);
Currs = malloc(NumOfNames * sizeof *Currs);

Then you can access Heads[0] through Heads[NumOfNames - 1] (inclusive), assuming the allocations succeeded of course.

unwind
  • 391,730
  • 64
  • 469
  • 606
1

What you have there is static allocation and the memory is allocated on stack (actually not really on stack, since these are global variables - see the comments). It means that the size of the array needs to be known at compile time. On the other hand, you want to be able to allocate memory at run time since you don't know the size (NumOfNames) earlier. That is called dynamic allocation and you need malloc (or calloc,...) for that. Such memory is allocated on heap. For more information on this please read e.g. these:

To do what you want using malloc you can do this:

struct Node
{
    int Line;
    struct Node *Next;
} ;

struct Node** Heads;
struct Node** Currs; 

int NumOfNames;

int main() {
    // ...
    NumOfNames = 42;
    Heads = malloc(NumOfNames * sizeof(struct Node*));
    Currs = malloc(NumOfNames * sizeof(struct Node*));

    // if you want to allocate the Nodes too...
    int i;
    for (i = 0; i < NumOfNames; i++) {
        Heads[i] = malloc(sizeof(struct Node));
        Currs[i] = malloc(sizeof(struct Node));
    }
    // ...
}

When you allocate memory dynamically (using malloc, calloc, realloc,...), please be sure to free() it as well when you don't need it anymore.

Community
  • 1
  • 1
geckon
  • 8,316
  • 4
  • 35
  • 59
  • In the OP's case the variables global variabls and therefore they are not on the stack. – Jabberwocky May 05 '15 at 12:20
  • @MichaelWalz You are right. Global variables are not placed on a stack (but not on heap either). They're still allocated statically though. For further reading on global variables: http://stackoverflow.com/questions/1169858/global-memory-management-in-c-in-stack-or-heap – geckon May 05 '15 at 12:24
1

If you are allowed to use C99 (flag -std=c99 for gcc), then you have variable length arrays available. Here too.

// From the wikipedia page
float read_and_process(int n)
{
    float vals[n];

    for (int i = 0; i < n; i++)
        vals[i] = read_val();
    return process(vals, n);
}

Your Heads and Currs can then use a variable as size. On the other hand, you can't make them global, you'll have to pass pointers and sizes around to sub-functions.

Note also that if you are new to programming and C, the use of malloc and free is something you really want to learn.

Note also that VLA are not very popular, for example because they don't return errors if you don't have enough memory to allocate space for them, possibly resulting in hard to debug and dangerous problems.

I felt I had to write this alternative, but I also really think you should go for malloc and free, and learn how this is done. Check if malloc returned NULL and exit gracefully :)

Community
  • 1
  • 1
Gauthier
  • 40,309
  • 11
  • 63
  • 97