-2

I write c embedded on STM32F437VI. At some point, I need to parse some strings that contain numbers, as float numbers. I use atof and it works always with the correct result, except for this one weird case. If the string is 0 or 0.0 it gives 2.

I have included stdlib.h and even tried (float)atof() to typecast, but for some weird reason, the float variable has always the value 2 from the atof("0") operation and the double value has the correct 0. Why is this happening? Thank you all in advance.

#include "stdio.h"
#include "stdlib.h"

int main(void)
{
    char test[] = "0";
    float val1;
    double val2;

    val1 = atof(test);
    val2 = atof(test);

    return 0;
}

I expect the obvious result of 0 to the float variable as well, but it keeps getting the fixed 2 value.

UPDATE: This code section is part of a much bigger project and there is no point in elaborating on the project. I have custom Makefile with LDFLAG option

"-mfloat-abi=hard -mfpu=fpv4-sp-d16 -u _printf_float".

Could this affect this issue?

As the MCV example is concerned, in main.c I have the above code section and I got the results mentioned. Can anybody think of any reason atof() behaves in this way? Of course I have used online c compiler as well with the exact same code and the result is of course 0. I guess if something was very very wrong with the stdlib library, then atof() would not work for all the other cases as well. But it fails only for "0" and only with the result 2 assigned to the float variable.

I watch the variables realtime with Ozone debugger software. Could the reason be the floating point implementation on STM32F4 mcu used? A missing parameter in the custom Makefile or something like that?

Clifford
  • 88,407
  • 13
  • 85
  • 165
BabisI
  • 25
  • 1
  • 7
  • 3
    With the code you show, it's going to be impossible for us to replicate your problem. Please try to create a [mcve] to show us. – Some programmer dude Jan 18 '19 at 11:15
  • Does your toolchain have configurable floating point support? Also, some toolchains allow disabling more complex features of `scanf` library functions, and may also affect `ato*` and `strto*` functions. – user694733 Jan 18 '19 at 11:24
  • 2
    The answer to "my code is to big to show here" is MCVE. The answer to "too secret" is MCVE. If you show only the code lines in which you guess the problem is, but where you have not found it yourself, then in alll likelyhood, the error is somewhere else. Make an MCVE to make sure that you and we are looking at the same thing. If we cannot reproduce it, then it is time to talk about compiler versions and other attributes of your environment. Read the MCVE link provided by Some and apply the concept to your code. Asking about perceived misbehaviour without an MCVE is off-topic. – Yunnosch Jan 18 '19 at 11:38
  • 1
    If what you show is enough for you to replicate the problem for you, then put it into a `main` function, add header files, and make it complete. Then tell us that it's the minimal code to replicate the problem (and of course make sure that you really *can* replicate it using the program), and add all details you can about build and run settings and environments. – Some programmer dude Jan 18 '19 at 11:45
  • How are you validating whether the value is `0` or `2`? With `if`? With `printf()`? ?? – pmg Jan 18 '19 at 11:51
  • I watch the variables realtime with Ozone debugger software – BabisI Jan 18 '19 at 12:00
  • When you write “in main.c I have the above code section and I got the results mentioned”, do you mean the code shown here is the **complete program** that reproduces the problem for you or that the code shown here is merely included in a larger program that has the problem? If the latter, then the code here is not an MCVE. There would almost certainly be something else in the complete code causing the problem. You should remove other code from the program until either the problem vanishes (which reveals that other cose caused the problem) or the remaining code is acceptable to show us. – Eric Postpischil Jan 18 '19 at 12:51
  • 1
    Your new code does not use the value returned by `atof`. The compiler could optimize variable allocation. It might happen that the debugger does not show real value. You should try to print the results and see what you get. – Gerhardh Jan 18 '19 at 13:04
  • I have also added an if case: if (val1 == 2) {//do smth} And yes it goes inside the if case, thus the value is indeed 2 and it is not a debugger issue i guess.. Besides, if it is indeed a debugger issue, why for all the other possible values are they shown correctly? – BabisI Jan 18 '19 at 13:29
  • You should never use atof to begin with. Use strtof. – Lundin Jan 18 '19 at 14:48
  • Anyway, what happens when you declare both variables as volatile? I suspect this is something silly, like one of the variables never getting written to since it is never used. – Lundin Jan 18 '19 at 14:49

2 Answers2

4

First, your question lacks a Minimal, Complete, and Verifiable example.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char test[] = "0";
    float val1;
    double val2;

    val1 = atof(test);
    printf("%f\n", val1);

    val2 = atof(test);
    printf("%f\n", val2);
}

Output:

0.000000
0.000000

<°)))<()

Or your standard library implementation is fubar.

Swordfish
  • 12,971
  • 3
  • 21
  • 43
1

It looks like the cause of your problem is in the updated question text:

UPDATE: This code section is part of a much bigger project and there is no point in elaborating on the project. I have custom Makefile with LDFLAG option

"-mfloat-abi=hard -mfpu=fpv4-sp-d16 -u _printf_float".

Assuming these options are changes vs the defaults, what you're doing is telling the compiler to generate code for a different ABI from your toolchain's library ecosystem. The code generated for main expects the result of atof in a floating point register, but atof is using the standard ABI, which passes floating point arguments and return values in general-purpose registers. Thus, main is just reading whatever junk happens to be left in the floating point registers used for return values.

See if your problem goes away if you remove -mfloat-abi=hard. If so, you've probably found your problem. You need to either build a toolchain and libraries for the hardfloat ABI, or stick with the default non-hardfloat calling convention.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711