Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

dougphd

macrumors member
Original poster
Apr 28, 2016
70
0
I have this structure
Code:
struct hlv {
 char name[20];
 int num;
 float range;
 float vol;
 float width;  //range/vol
 struct hlv *next;
};
/[code]

for which I can declare
[code]
struct hlv foundLink[10];
/[code]
but for which I cannot allocate memory
[code]
struct hlv *foundLink;
for (i = 0; i < 10; i++)
   foundLink[i] = (struct hlv*) calloc(1, sizeof(struct hlv));
/[code]

Why not?
 
There are a couple issues. First, you apparently have a "foundLink" pointer variable that's in local scope and a separate "foundLink" array declared in global scope. The foundLink local variable will mask the global one. Don't name a local variable with the same name as a global variable.

Then beyond that, calloc() returns a pointer. The foundLink[10] array is declared as an array of 'struct hlv' records, not an array of 'struct hlv" pointers. In your code, the proper declaration would be "struct hlv *foundLink[10];" given what I believe is your intended usage. But normally, you should never need such an array.

I'm going to include a complete example of reading a simple file into structs using a singly-linked list. Notice there are no arrays declared anywhere.

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

struct rec
{
    struct rec *next;

    int a;
    int b;
} *head=NULL, *tail=NULL;

// Add an allocated record to the list
void addToList(struct rec *r)
{
    // Check to set the head pointer
    if (head == NULL)
    {
        head = r;
    }

    // Link the tail if there is one
    if (tail != NULL)
    {
        tail->next = r;
    }

    // Add new record to tail
    tail = r;
}

void dumpRecords()
{
    struct rec *curr = head;

    // Iterate through the record pointers
    while(curr != NULL)
    {
        printf("Record a=%d  b=%d\n", curr->a, curr->b);

        // Advance the current record pointer
        curr = curr->next;
    }
}

void readFile(const char *filename)
{
    FILE *f;
    int fA, fB;

    if ((f = fopen(filename, "r")) == NULL)
    {
        perror("couldn't open file");
        return;
    }

    while (fscanf(f, "%d %d", &fA, &fB) == 2)
    {
        struct rec *r = calloc(1, sizeof(struct rec));

        if (!r)
        {
            break;
        }

        r->a = fA;
        r->b = fB;
        addToList(r);
    }

    fclose(f);
}


int main(int argc, char *argv[])
{
    char *fn;

    if (argc >= 2)
    {
        fn = argv[1];
    }
    else
    {
        fn = "test.dat";
    }

    readFile(fn);
    dumpRecords();
}
 
Last edited:
I just saw your reply. I'll have two hours on the train later. It's a great time for C programming. I'll look in detail then.
Thanks.
 
Actually, I think this is what I was trying to do.
struct hlv *foundLink;
foundLink = (struct hlv*) calloc(10, sizeof(struct hlv));
Something of a cockpit error but that's what happens when you don't program often.
 
Actually, I think this is what I was trying to do.
struct hlv *foundLink;
foundLink = (struct hlv*) calloc(10, sizeof(struct hlv));

Both this and that thing in your first post are incorrect usages of a linked list.

The point of a linked list is that each element knows the position of the next element.
Therefore, you only need to have ONE pointer (pointing at the first element) to represent your linked list.
As in:
Code:
MyLinkedList * first;
first = (MyLinkedList*)malloc(sizeof(MyLinkedList));

This is your first element that also represents the WHOLE linked list.

If you, for some reason, wanted to allocate memory for a 10-element linked list (without writing any useable data into those elements), that would be:
Code:
MyLinkedList * first;
first = (MyLinkedList*)malloc(sizeof(MyLinkedList));
MyLinkedList * current = first;
for (int i = 0; i < 9 ; ++i) {
    current->nextElement = (MyLinkedList*)malloc(sizeof(MyLinkedList));
    current = current->nextElement;
}
note that we created the first element manually, and then appended the next element nine times, in a cycle.

Again, the important thing to grasp is that there's no difference between one element and the whole linked list - they're the same pointer. If you take, say, the fifth element of your ten-element linked list, what you have is essentially the first element of a five-element linked list. Same thing.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.