(Note: In an early version of this question I assumed that I used references the wrong way. It turned out to be a different problem and I made changes to the title/question accordingly.)
My code is intended to be compiled with avr-gcc and runs on an ATmega168p micocontroller.
I have the below function in C that is supposed to parse a float value from a buffer (char array) and assign it to a corresponsing float variable:
void read_float_from_buffer(float *var, char *buffer, uint8_t start, uint8_t end) {
char val_buf[8];
// transfer characters representing float to a temporary buffer
uint8_t p=0;
for (uint8_t i=start;i<=end && p<7;i++) {
val_buf[p++]=buffer[i];
}
val_buf[p]='\0';
// perform sscanf on this temporary buffer
float buf=-1;
if(sscanf(val_buf, "%.2f", &buf)==1) // this fails, sscanf returns 0
*var=buf;
}
I have another function find_float_in_buffer() which searches a char buffer for the start and end indices of a float value. The function read_float_from_buffer() is called within this function:
float a_float_variable=0.;
void find_float_in_buffer(char *buffer) {
uint8_t start,end=0;
/*
I do some magic here to find out where my float string starts and ends
*/
read_buffer_float(&a_float_variable,buffer,start,end);
}
From my understanding this should work, but for some reason, scanning the val_buf temporary buffer fails (sscanf returns 0).
My question: is the way I'm passing the reference to buffer to read_buffer_float in find_float_in_buffer correct? I thought I finally understood how to pass pointers or references to functions, but I'm not sure if this is how you would pass a pointer in a function on to another function.
Edit: I'm running this code on a Atmel microcontroller and compiling using avr-gcc.
Edit 2: I removed my entire firmware and came up with the following MWE:
#define F_CPU 8000000UL
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <util/delay.h>
#include "src/peripheral-core/uart.c"
int main() {
_delay_ms(200);
uart_init();
uartWriteString("application started\n\r\0");
char test[]="12.34\0";
float testfloat=-1;
sscanf(test, "%f", &testfloat);
uartWriteString("teststring is:\t\0");
uartWriteString(test);
uartWriteString("\n\rscanned float is:\t\0");
uartWriteFloat(testfloat);
uartWriteString("\n\0");
for (;;) {
_delay_ms(1000);
}
}
For me, this prints:
application started
teststring is: 12.34
scanned float is: -1.000
To build the .hex file I run this command:
avr-gcc -std=gnu99 -c -Os -Wall -mmcu=atmega168p main.c -o main.o
avr-gcc -std=gnu99 -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega168p main.o -o main.elf
avr-objcopy -O ihex -j .data -j .text main.elf main.hex
AVR-GCC version:
avr-gcc --version gives avr-gcc.exe (GCC) 10.1.0
When I run the below equivalent on my developement system, it works.
#include <stdio.h>
int main() {
printf("application started\n\r\0");
char test[]="12.34\0";
float testfloat=-1;
sscanf(test, "%f", &testfloat);
printf("teststring is:\t\0");
printf(test);
printf("\n\rscanned float is:\t\0");
printf("%.2f",testfloat);
printf("\n\0");
}
But: When I pass "%.2f" to sscanf() as a format specifier (which is invalid as pointed out in the comments), this version fails with the same behaviour.
val_bufafter populating it to make sure it contains what you expect. Also, there's no precision field inscanfformats.I do some magic here. It's difficult to help without complete code. For example, maybe that "magic" is wrong maybebufferdoesn't contain what you think it does, etc. The actual parameter passing seems correct in terms of passing the buffer between the functions. Please provide a minimal reproducible example for further help.%.2fis an invalid format specifier for*scanf. Do you not get a compiler warning about it? I do. (Do you not have compiler warnings enabled?!) You probably just want%f.val_bufand confirmed that it contains a float string ("8.76" in my test case). Is that thing with the precision field also true for sscanf?scanffamily.