Memory Reference Sent to Double Pointer

So I'm looking for clarification on something that works. I'm pretty sure I understand what is happening but wanted to be sure before proceeding with my work.

I have a function defined as follows:

name* createName(char* firstName, char* lastName)
{
    name* newName = (name*)malloc(sizeof(name));

    initStringValue(&newName->firstName, firstName);
    initStringValue(&newName->lastName, lastName);

    newName->firstNameSize = strlen(newName->firstName);
    newName->lastNameSize = strlen(newName->lastName);

    return newName;
}

The structure "name" is defined like so:

struct name 
{
    char* firstName;
    char* lastName;

    int firstNameSize;
    int lastNameSize;
};

Another function responsible for the copy of the name strings is written like the following:

void initStringValue(char** destination, char* source)
{
    int length = strlen(source) + 1;
    int size = length * sizeof(char);
    *destination = (char*)malloc(size);
    memset(*destination, 0, size);
    strcpy(*destination, source);
}

If I'm understanding what I've done here, by using the & operator I've signified that I wish to send not a value but its associated memory address. In a statement such as

&newName->firstName

where the struct member firstName is a char* I've indicated that I would like to send the memory address of this pointer and not the pointers value (which happens to be a memory address in and of itself). The -> operator dereferences this pointer to the member of the pointer but then the & operator essentially returns us to the firstName memory reference instead, allowing me to manipulate information at that memory reference.

Now things get wild (for me anyway). To actually work with that memory reference, I end up using double indirection (so very passive aggressive). As it follows a memory reference (like that of &newName->firstName) sent to a char** like that of char** destination in the initStringValue function, would be a pointer of a pointer where the latter is assigned the memory reference returned by &newName->firstName. By then using *destination I'm working with a pointer pointed to the memory reference of &newName->firstName. Or stated differently, a pointer whose first and only member is the memory reference of newName->firstName.

Am I actually understanding this correctly?

1 answer

  • answered 2017-06-17 18:11 4386427

    Am I actually understanding this correctly?

    After reading your description, I'll say yes

    I'll try to explain it with some examples.

    If you do this:

    void foo(int a)
    {
        a = 5;
    }
    
    int main()
    {
        int a = 10;
        foo(a);
        printf("%d\n", a);
        return 0;
    }
    

    You'll get the output: 10

    That's because the function parameters are local variables to the function. In other words - any change made to a function parameter is lost when the function returns, i.e. the variable in main will not be changed.

    If you want a function to change the value of a variable in main (aka in the caller), you'll have to pass a pointer. Like:

    void foo(int* a)  // notice int*
    {
        *a = 5;       // notice *a
    }
    
    int main()
    {
        int a = 10;
        foo(&a);       // notice &a
        printf("%d\n", a); 
        return 0;
    }
    

    This will output: 5

    This is a general rule regardless of the type. I used int in the example but it applies to any type - pointers as well.

    So let's take an example with a pointer:

    void foo(char** a, int size)    // notice char**
    {
        *a = malloc(32);            // malloc memory
        strcpy(*a, "Hello world");  // copy some data into the memory
    }
    
    int main()
    {
        char* a = NULL;   // a is not pointing to anything yet
        foo(&a);
        // Now a points to the malloc'ed memory
        printf("%s\n", a);
        return 0;
    }
    

    This will output: Hello world