function pointer in c - understanding

Hi,

I reading the c code below and looking to implement and understand it in c and, the first segment calls read_temperature, which reads a temperature sensor.

I'm trying to understand it.

  1. Is read_temperature() a pointer to a function? What is the benefit of this?

  2. read_temperature takes the address of length?

  3. Why is it necessary to initialise tempbuff[] to all zeros using memset().

  4. What does `temp_reading&0xff do?

  5. Why is it necessary to do *templength = 5; at the end?

static int length;
static unsigned address

address = (unsigned int)read_temperature(& length);  
PRINTF("Temperature is located at memory [%x] and its length is [%d] \r\n",address,length);
uint8_t tempbuff[8];

uint8_t * read_temperature(int *templength)
{
    memset(tempbuff, 0, sizeof(tempbuff));
    int temp_reading = readTemperature(); //This returns temperaure reading

    tempbuff[0] = 'T';
    tempbuff[1] = temp_reading&0xff;
    tempbuff[2] = (temp_reading>>8)&0xff;
    tempbuff[3] = (temp_reading>>16)&0xff;
    tempbuff[4] = (temp_reading>>24)&0xff;
    
    *templength = 5;  
    return (&tempbuff[0]);
}

uint8_t * read_temperature(int *templength)

  1. Is read_temperature() a pointer to a function? What is the benefit of this?

No, its a call to a function which returns a pointer to a "uint8_t"

  1. read_temperature takes the address of length?

It accepts a pointer to length.

I can think of no good reason the function should set the entire length of the buffer to zero, and quite a few why it shouldn't.

The '&' operator? To mask only the eight least significant bits of the variable.

The function call 'read_temperature()' returns a pointer,
And the name of any function without brackets is effectively a pointer to that function (unrelated, but may clear somethings up).

It takes a pointer to the length variable, however it is filling it with data, its not expecting you to pass data in.
The function returns a pointer to the first array element of 'uint8_t tempbuff[8];'

Clearing the memory before use is common, as there is no guarantee that the memory your variable occupies will be zero, thus filling your variable with random data (there are some exceptions, however this is in general).

It is a bit mask that removes the high-byte data (only working with the lower byte). It preserves any data in the lower 8 bits, but sets bits 8-15 as zero (int is 16 bits, which temp_reading is).

It is dereferencing the pointer so you can write to the actual variable. Without it you'll overwrite its pointer.

Personally, it does not look like a well constructed function. Using global variables while expecting you to not know the length of the data it creates seems kind of wasteful. It could simply expect tempbuff to be 5 elements long.

It'not a pointer to a function.

read_temperature is a function that returns a pointer to an uint8_t and takes as argumemt a pointer to a variable.

Because read_temperature returns a pointer, there id no way that the calling function can know how many elements are in there (currently it's 5, but a future implementation might be 2 or 8 or ...). To cater for that, the code in the function places the number of elements in templength so the calling function knows how many elements there are in the tempbuff.

Many thanks for your help guys.

Hi,

I have one further question if you don't mind.

Just after the calling function, it says

PRINTF("Temperature is located at memory [%x] and its length is [%d] \r\n",address,length);

But read_temperature does not return 'length', it returns a pointer to tempbuff[].

How does the 'calling code' see length if it is not returned from read_temperature?

Thanks

*templength = 5;

This puts the value 5 into "length"

In the initial code:

static int length = 0;
static unsigned address

address = (unsigned int)read_temperature(& length);

the call to read_temperature() is passed the memory address (lvalue), because of the address-of operator (&) in front of length, where the variable named length resides in memory. Let's assume length resides at memory address 100. This means that memory addresses 100 and 101 hold the value of length, which is 0 right now. So the function call above sends 100 to the function, not 0.

This line is called the function's signature:

uint8_t * read_temperature(int *templength)

the argument to the function is a pointer to an int variable named templength. This is the syntax used to inform the compiler that it is receiving a memory address (lvalue) instead of the more common copy of a variable's value (rvalue). In other words, it knows it is receiving a memory address where some variable lives.

As AWOL said, this statement:

*templength = 5;

tells the compiler: "Go to the memory address held in templength (i.e., 100) and copy the value 5 into those memory locations. It knows it has to use 2 bytes because the function signature told it that it was passed a pointer to an int data type. So, it takes the value 5, pads it out to fill 2 bytes, and sticks those 2 bytes starting at memory address 100.

Now, back in loop(), length now equals 5.