0

I am getting a bit confusing with pointers, I want to update the variable tmpTwoComplement, if I do update as in this code snippet, it does work:

int16_t max30205MeasureTemperature(int16_t *tmpTwoComplement) {

    char regT = MAX30205_REG_TEMPERATURE;

    max30205_raw_data rawTemp;

    max30205_read_reg_as_temperature(regT, &rawTemp);

    *tmpTwoComplement = rawTemp.swrd;
}

but this one doesn't, why?

int16_t max30205MeasureTemperature(int16_t *tmpTwoComplement) {

    char regT = MAX30205_REG_TEMPERATURE;

    max30205_raw_data rawTemp;

    max30205_read_reg_as_temperature(regT, &rawTemp);

    tmpTwoComplement = &rawTemp.swrd;
}

I always call the above function as

max30205MeasureTemperature(&registerTemp);

being

typedef union max30205_raw_data {
    struct {
        uint8_t lsb;
        uint8_t msb;
    };
    struct {
        uint16_t magnitude_bits:15;
        uint16_t sign_bit:1;
    };
    uint16_t uwrd;
    int16_t swrd;
} max30205_raw_data;

tempSamplesUpdatedMAX30205 = true;
chqrlie
  • 131,814
  • 10
  • 121
  • 189
ndarkness
  • 1,011
  • 2
  • 16
  • 36
  • 1
    First one works, second doesn't. Clearly as in C language, there is no `pass by reference`. Your pointer is local variable and you only change where local variable points to. WIth first example (dereference included), you write the data to the memory pointed to by your variable. Even worse, in second example you are trying to assign pointer to local variable. – unalignedmemoryaccess Aug 09 '19 at 09:36
  • refer to [Changing address contained by pointer using function](https://stackoverflow.com/questions/13431108/changing-address-contained-by-pointer-using-function) for details on why the second code doesn't work like you think – Sander De Dycker Aug 09 '19 at 09:39
  • 1
    you write "I want to update the variable tmpTwoComplement" however it appears what you actually want to do is update the contents of the memory location whose address is stored in the variable `tmpTwoComplement` – M.M Aug 09 '19 at 10:00

3 Answers3

1

This

tmpTwoComplement = &rawTemp.swrd; /* assigning pointer with locally created struct var address */

doesn't work as tmpTwoComplement assigned with locally created structure variable address & this scope is within this max30205MeasureTemperature() function only.

When control comes back to here

max30205MeasureTemperature(&registerTemp); /* max30205MeasureTemperature modifies registerTemp in second scenario */

registerTemp no longer points to previews address & now it may not point to valid address.

Achal
  • 11,821
  • 2
  • 15
  • 37
  • Then how do I fix the first case to make it available outside the function `max30205MeasureTemperature()`? – ndarkness Aug 09 '19 at 10:26
1

In the second case only the pointer tmpTwoComplement is changed. Now it points to the temporary value rawTemp.swrd. Since a parameter is working like a local variable, it has no effect at all, because no other expression follows. The variable registerTemp at the caller's site is not changed.

the busybee
  • 10,755
  • 3
  • 13
  • 30
1
*tmpTwoComplement = rawTemp.swrd;

You write the value of rawTemp.swrd to the location pointed to by tmpTwoComplement, which happens to be the address of the variable registerTemp because of the way you call the function: max30205MeasureTemperature(&registerTemp). So after exit from the function, registerTemp will contain a copy of the value inside rawTemp.swrd.

tmpTwoComplement = &rawTemp.swrd;

In this case. you copy the address of the local variable rawTemp.swrd into the pointer tmpTwoComplement, overwriting the address of registerTemp which was previously in it. After exit from the function, nothing happens because all internal variables of the function cease to exist and your code has not written into any variable outside of the function.

What you should understand is that tmpTwoComplement is a pointer to some memory location. You can always make it point to a different location as in your second case. But that, in itself, accomplishes nothing. What you want to actually do is write to the target memory location it points to. This is done by using *tmpTwoComplement=.

EDIT: Why don't you do it this way, avoiding pointers altogether?

int16_t max30205MeasureTemperature(void) {    
    char regT = MAX30205_REG_TEMPERATURE;

    max30205_raw_data rawTemp;

    max30205_read_reg_as_temperature(regT, &rawTemp);

    return rawTemp.swrd;
}

and then read it with,

registerTemp = max30205MeasureTemperature();
th33lf
  • 2,177
  • 11
  • 15