sprintf only prints -0.00000

May 11, 2008
21,965
1,354
126
Hi, i am fiddling around with my gcc compiler for my arm7tdmi.
I am using sprintf from gcc.

Code:
fl1 = 3.14567;
test = sprintf(sparray, "float value %8.5f\r\n", fl1);

I tried using float for single precision and double but both give the same 0 value.
I just do not get what i am doing wrong.
Have i forgotten to add a library to the linker or something or some header file gcc needs ?
The sprintf seems to work, i tried decimal values and it works fine.
But when i try to print floating point values it always gives -0.0.
The bin files does get about 27kB larger , a lot of functions are added.
 

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,597
4,502
75
I wrote a test, and I can't reproduce this:
Code:
#include <stdio.h>
int main(void) {
  float fl1 = 3.14567;
  char sparray[100];
  sprintf(sparray, "float value %8.5f\r\n", fl1);
  printf("%s", sparray);
}
When run:
Code:
$ ./printest 
float value  3.14567
 
May 11, 2008
21,965
1,354
126
Thanks for testing.
I use an old cross compiler for arm7tdmi, i am afraid that i have to dig into it with obj dump and hope to find what goes wrong.
I also fear that the function may need a hardware fpu and the mcu i use does not have that.
I have this little project that needs floating point calculations. Would be nice to use the old mcu for this project.

To be honest.
All i want is to have a ftoa and single precision would be sufficient.
An ftoi would great too.
I have been reading about IEE754 but i have still not a complete grasp what each bit represents and when a number is normalized or denormalized.
Otherwise i would just make an attempt to write my own ftoa.
 
May 11, 2008
21,965
1,354
126
This is strange, i dump the raw hex values from memory, and as it turns out, the gcc compiler i use converts floating point values to integers.
I created an array of 4 floating point values :
single precision , thus 4 bytes each.

Code:
float                                    flparray[4];


I then initialize the array and then write values ot it.

Code:
    MemSet(flparray,0,16);
    Sci0DumpHex((uint32_t) flparray[0]);
    Sci0DumpHex((uint32_t) flparray[1]);
    Sci0DumpHex((uint32_t) flparray[2]);
    Sci0DumpHex((uint32_t) flparray[3]);
   
    flparray[0] = 3.14567;
    flparray[1] = 2.0;
    flparray[2] = 4.0;
    flparray[3] = 8.0;
    Sci0DumpHex((uint32_t) flparray[0]);
    Sci0DumpHex((uint32_t) flparray[1]);
    Sci0DumpHex((uint32_t) flparray[2]);
    Sci0DumpHex((uint32_t) flparray[3]);

Now when i print it , i get these results :
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00

00 00 00 03
00 00 00 02
00 00 00 04
00 00 00 08

All are turned into integers.
The 3.14567 should read as 0x404952a8 or a8524940.
The 2 should read as 0x40000000 or 0x00000040.
The 4 should read as 0x40800000 or 0x00008040.
The 8 should read as 0x41000000 or 0x00000041.

I think i found the problem.
It is not the supplied sprintf or snprintf that is the issue.
 

Schmide

Diamond Member
Mar 7, 2002
5,694
936
126
I can't believe it actually compiled without an explicit float or double declaration. I know visual studio would choke on it.
 
May 11, 2008
21,965
1,354
126
Well, i made an eror in my testing. I casted the floating point value to an uint32_t and then printed it.
That was wrong, I wanted to know the explicit value in memory without casting it.

This is sort of the correct way, although the compiler warns about incompatible pointer types.
Code:
    float                                   flparray[4];
   uint32_t                           *pointer;

   flparray[0] = 3.14567;
    flparray[1] = 2.0;
    flparray[2] = 4.0;
    flparray[3] = 8.0;
 
    pointer = &flparray[0];
    Sci0DumpHex((uint32_t) *pointer);
    pointer = &flparray[1];
    Sci0DumpHex((uint32_t) *pointer);
    pointer = &flparray[2];
    Sci0DumpHex((uint32_t) *pointer);
    pointer = &flparray[3];
    Sci0DumpHex((uint32_t) *pointer);

And i get these values as expected :

40 49 52 A8
40 00 00 00
40 80 00 00
41 00 00 00

Now, it is a matter of finding out if it is an endianess problem.
The mcu i use is hardwired in the little endian format.
I am going to translate these values and then see what happens.


edit:
I mirrored the bytes to see if it was an endianess problem and i still do not get the correct output.
Back to the drawing board. :(


Since it can be small numbers, i also tried the scientific notation to see if that would help, but i get all these weird results...

Value : 3.14567:
Code:
char                                   sparray[32];
test = snprintf(sparray,30, "float E  %e\r\n", flparray[0]);

either :
1.047230e-317
or when i reverse the bytes :
6.631237e-315

I compared it with an online ieee converter and it does not even come close.
 
Last edited:
May 11, 2008
21,965
1,354
126
I might have a newlib issue. Newlib is for embedded mcu's and the version i have may have the floating point capabilities of printf and all related functions disabled or even not supported by default.
I have to look into that.
 
May 11, 2008
21,965
1,354
126
Sigh, There is something wrong with the newlib for arm7tdmi that i use. I checked all the headers and it seems i have correct endianess enabled.
What i have not been able to figure out if the stdio function expect floating point values in VFP or FPA format. This is a bit old compiler and most sites are giving error 404.

For now i have given up on getting sprintf and printf to work. This was an issue with this older mcu model and almost all sites are out of commision.
I just wanted to make something for the last time with this mcu.
Thus i searched for a float to ascii function and this seems to work what i have found here: :)
http://www.geeksforgeeks.org/convert-floating-point-number-string/
I do not have to do the heavy lifting for now.

Now i can test if the newlib library i have can even do floating point math at all.

For my other projects i will be using a cortex m4 or m3 i have been playing around with. And that line of mcu has much better support from the manufacturers.
 
May 11, 2008
21,965
1,354
126
To add for other people searching, with newlib, adding thew option -u and the name of the function links in floatingpoint support when needed.
Like for example adding -u _printf_float to the linker flags should help. But this is if i am not mistaken mainly for newlib nano and should not have to be added for newlib itself.
I have tried this but for some reason it is not working for me although i have newlib version 1.20.
I have looked around the header files but i have not spend much time.
Strange thing is that i did not find any reference to newlib nano, so it should just be general newlib.
It must be some dependency that is set wrong, could be my linker file ***.ld that has a bug or something else.
I could really go out of my way and compile the newlib myself and add the headers and libraries ending on ***.a but for now the ftoa from the previous post is sufficient for me.
The processor does not have to do that much, it is just constant measuring and displaying and doing some graphic stuff.

For more information :

https://github.com/32bitmicro/newlib-nano-1.0/blob/master/newlib/README.nano