Search code examples
cpass-by-referencedereference

Strange behaviour using pass-by-reference / dereferencing


Here is my demonstration code:

#include <stdio.h>

#define WORK 0

typedef struct FooStruct {
    int x;
} FooStruct;

void setX(FooStruct *foo_ptr) {
    FooStruct foo = *foo_ptr;

    if (WORK) {
        foo_ptr->x = 10;
    } else {
        foo.x = 10;
    }
}

FooStruct makeFoo() {
    FooStruct foo = { 0 };

    setX(&foo);

    return foo;
}

int main(void) {
    FooStruct foo = makeFoo();

    printf("X = %d\n", foo.x);

    return 0;
}

If WORK is defined to be 1, the code executes as expected and prints "X = 10".

However, if WORK is set to 0, it instead prints "X = 0", or if the FooStruct isn't default initialised (i.e. change FooStruct foo = {}; to FooStruct foo;), valgrind will throw a value uninitialized error on the printf line.

I'm sure this is due to a gap in my understanding, but to me the two different WORK branches should essentially be identical in operation, so I'm not sure where the misunderstanding is coming from.

This is compiled with gcc 8.2.0 with/without valgrind with equal results.

=======================

EDIT:

Simplified example:

#include <stdio.h>

#define WORK 0

void setX(int *x_ptr) {
    if (WORK) {
        *x_ptr = 5;
    } else {
        int x = *x_ptr;
        x = 5;
    }
}

int main(void) {
    int x = 0;
    setX(&x);

    printf("X = %d\n", x);

    return 0;
}

Solution

  • The code seems to be working as expected when you #define WORK 0 too. If you set a member in a copy of a structure, you shouldn't expect the original to be modified.

    You have:

    void setX(FooStruct *foo_ptr) {
        FooStruct foo = *foo_ptr;
    
        if (WORK) {
            foo_ptr->x = 10;    // Modify the structure pointed to by foo_ptr
        } else {
            foo.x = 10;         // Modify the local copy of the structure
        }
    }
    

    Because you've made an MCVE (Minimal, Complete, Verifiable Example — thanks!), there is nothing done with the modified copy of the structure in setX().