'variable' may be used uninitialized in this function, have a working workaround but don't understand why

Viewed 2527

I have searched and found a lot of similar questions (with undoubtly good answers) but I haven't found one that I understand completely. I have found a solution that does work and I am really just trying to understand what I do wrong in the first example...

I wrote a function that calculates pitch/roll from raw accelerometer values with declaration:

uint8_t calcPitchRoll (imu_t * imu, float * pitch, float * roll);

The calling function looks like (line numbers for reference):

518 float * pRollValue, * pPitchValue; // prepare pointers to floats to store results
519 *pRollValue = 0; // initialize variables
520 *pPitchValue = 0; // initialize variables
521 calcPitchRoll (imu, pPitchValue, pRollValue);

However, that results in the compiler warnings:

main.c:519:25: warning: 'pRollValue' may be used uninitialized in this function
main.c:521:26: warning: 'pPitchValue' may be used uninitialized in this function

The following however does work:

float PitchValue, RollValue = 0;
float * pRollValue = &RollValue;
float * pPitchValue = &PitchValue;
calcPitchRoll (imu, pPitchValue, pRollValue);

To me, both examples seem to have the same "state" when calling the calcPitchRoll function, but the compiler disagrees.

What I (think I) understood is that *pRollValue = 0 writes that value to the variable, so I'd think at that point the variable has space allocated ànd a value. Is that an incorrect understanding?

1 Answers

There are a huge difference in your two code examples.

Look at this:

518 float * pRollValue, * pPitchValue;  // Here pRollValue is uninitialized
519 *pRollValue = 0;                    // Here you dereference pRollValue (due to the *)
    ^        
    |                           // So you dereference an uninitialized pointer
    |
    Dereference of uninitialized pointer

Here

float PitchValue, RollValue = 0;
float * pRollValue = &RollValue;  // You define a pointer and at the
                                  // same time you initializes it to
                                  // point to a float

So the two code parts are completely different.

So you need to understand the difference between a pointer to an object of type T and a object of type T.

Code like

float * pF;

will give you memory for holding a pointer to float but there is no place to store the float itself. You need to assign a value to the pointer so that it points to a float.

So you need something like:

float * pF;
float myFloatVariable;
pF = &myFloatVariable;  // Now pF points to myFloatVariable

*pF = 42;               // These two statements both sets
myFloatVariable = 42;   // the variable myFloatVariable to 42

An alternative approach is dynamic allocation - like:

float * pF = malloc(sizeof *pF);
assert(pF != NULL);

*pF = 42;               // This sets the dynamic allocated float to 42
Related