Search code examples
cpointersstructpointer-to-pointer

Assigning values to properties of a 'struct ** record'


I'm having troubles understanding the C double-pointer concept. Essentially, I'm trying to write code which will check if record_1 hasn't been set yet. If not, set it. If it has been set, we'll add a new struct record newRecord to the first records .next pointer.

I'm using a double pointer because it's required by the professor

I've tried using firstRecord = malloc(sizeof(struct record*)); without any luck, as well as trying to dereference the firstRecord.

The while loop to iterate through the records located in the addRecord function also doesn't work as expected because I can't figure out how to deal with the double pointer.

struct record
{
    int                accountno;
    char               name[25];
    char               address[80];
    struct record*     next;
};

int addRecord (struct record ** firstRecord, int accountno, char name[], char address[])
{
    if (firstRecord == NULL)
    {
        // Segmentation Fault here
        // (*firstRecord)->accountno = accountno;
        // Assign the name to the newRecord
        // strcpy((*firstRecord)->name, name);
        // Assign the name to the newRecord
        // strcpy((*firstRecord)->address, address);
        // Initialize the next record to NULL
        // (*firstRecord)->next = NULL;
    }
    else
    {
        // Define a new struct record pointer named newRecord
        struct record newRecord;
        // Assign the accountno of newRecord
        newRecord.accountno = accountno;
        // Assign the name to the newRecord
        strcpy(newRecord.name, name);
        // Assign the address to the newRecord
        strcpy(newRecord.address, address);
        // Initialize the next record to NULL
        newRecord.next = NULL;
        // Create a new record and add it to the end of the database
        struct record ** iterator = firstRecord;
        // Iterate through the records until we reach the end
        while (iterator != NULL)
        {
            // Advance to the next record
            *iterator = (*iterator)->next;
        }
        // Assign the address of newRecord to the iterator.next property
        (*iterator)->next = &newRecord;
    }

    return 1;
}

int main() {
    struct record ** firstRecord;
    firstRecord = NULL;

    addRecord(firstRecord, 1, "Foo", "Bar");
    addRecord(firstRecord, 2, "Foo", "Bar");

    return 0;
}

Solution

  • It's not just required by the professor, it's required by your application. You want to allocate memory, and set a pointer that's defined outside your function to point to that memory. So naturally, you need to refer to that pointer. And C allows you to do that via a pointer to a pointer.

    So what you want your calling code to look like is this:

    struct record * firstRecord = NULL;
    addRecord(&firstRecord, 1, "Foo", "Bar");
    addRecord(&firstRecord, 2, "Foo", "Bar");
    

    You pass the address of the regular pointer, so that addRecord could write into it. And it does that by dereferencing its argument, like so:

    int addRecord (struct record ** pFirstRecord, /* ... */ )
    {
        if (pFirstRecord == NULL)
          return 0; // We weren't passed a valid address of a pointer to modify
    
        if(*pFirstRecord == NULL)
        {
          // Here we check if the pointed to pointer already points to anything.
          // If it doesn't, then proceed with adding the first record
        }
    }