sprintf, snprintf and floating point

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

sprintf, snprintf and floating point

3,426 次查看
JBM
Contributor V

I know this has been discussed many times and I have read the posts with no luck. 

 

I'm working with an MC9S08QE128.h with Codewarrior (version 5.9 and compiler version 5.0.14).  I'm trying to get sprintf to format  a floating point and not having any luck.  I have:

 

(1) Checked in libdefs.h that LIBDEF_PRINTF_FLOATING is 1. 

(2) I'm using the banked memory model and have include the ANSIBM.A library (float = double = 32 bits)

(3) Gone through all compiler options, "Double is IEEE32" is checked.

 

Is there something else required?

 

Also, where is snprintf()?  I don't normally use sprintf because of overflow issues, but snprintf() doesn't seem be where it's supposed to be (stdio).  The help file says it's there, but a search of stdio.h, does not show a prototype and the linker fails because the symbol "snprintf" is not defined which tells me the code doesn't exist.

 

Thanks for your help.

 

Brad

标签 (1)
0 项奖励
回复
11 回复数

1,499 次查看
CompilerGuru
NXP Employee
NXP Employee

- I don't know a "ANSIBM.A" library, use ansibfm.lib when using the banked memory model with -cf (IEEE32 for both float/double), see the readme.txt in lib/hc08c.

- Make sure that you have enough stack space, not sure if the default is sufficient.

- Also, how is it failing for you?

- the macro LIBDEF_PRINTF_FLOATING is considered when building the library, so if you use a stock library changing it wont help.

- I think I did provide some snprintf implementation in the forum once, basically the base code provides a call back which can be used to implement the boundary checking for snprintf too.

 

Daniel

 

0 项奖励
回复

1,499 次查看
JBM
Contributor V

Thanks for replying.  I've tried both ANSIBM.LIB and ANSIBFM.LIB with float an double arguments.  What I'm getting is the wrong float converted to a string such as "50.124" for M_PI.

0 项奖励
回复

1,499 次查看
CompilerGuru
NXP Employee
NXP Employee

 "50.124"  means that the floating point format you tell the compiler to use (with -cf, type option dialog) does not match the setting of the used library.

 

Please create a project with the wizard with the settings you want (increase the stack space, not sure if default is big enough) and see what you get there.

 

Check this web page:

 

http://babbage.cs.qc.edu/IEEE-754/Decimal.html

 

50.124 in IEEE64 is 0x40490FDF3B645A1D

PI as IEEE32 is is 0x40490FDB.

Note the identical leading digits, is appears that in your setup the compiler is using IEEE32 but a IEEE64 bit library is used. The readme.txt in lib/hc08c contains the options used to build the library. The floating point options you use (and the memory model) should match the ones used there.

 

Daniel

 

0 项奖励
回复

1,499 次查看
JBM
Contributor V

What you're saying makes sense so I took a look at the options as they are in the README.TXT file:

 

C   IEEE32/32 banked  HCS08 with MMU      ansibfm.lib  -W2 -Os -cs08 -MMU -Mt -Fd             -F2 -NoPath
C   IEEE32/64 banked  HCS08 with MMU      ansibm.lib   -W2 -Os -cs08 -MMU -Mt                 -F2 -NoPath
C   Integral only banked  HCS08 with MMU  ansibim.lib  -W2 -Os -cs08 -MMU -Mt -D__NO_FLOAT__  -F2 -NoPath
C++ IEEE32/32 banked  HCS08 with MMU      cppbfm.lib   -W2 -Os -cs08 -MMU -Mt -Fd             -F2 -NoPath
C++ IEEE32/64 banked  HCS08 with MMU      cppbm.lib    -W2 -Os -cs08 -MMU -Mt                 -F2 -NoPath
C++ Integral only banked  HCS08 with MMU  cppbim.lib   -W2 -Os -cs08 -MMU -Mt -D__NO_FLOAT__  -F2 -NoPath
               

Integral only libraries do not contain floating point operations.

Options used:
-W2:     Suppress warning and information messages
-Os:     Optimize for code size
-cs08:   Generate code for HCS08
-MMU:    Enable MMU support
-Ms:     Small memory model
-Mt:     tiny memory model
-Mb:     Banked memory model
-Fd:     Float and double is IEEE32
-F2:     ELF/DWARF 2.0
-NoPath: Do not write path information into object files
(for more details, see the provided online documentation)

I'm currently using ansibm.lib and as you can see, there is no ansibm.lib with a -Mb option for banked so I can't get one with the memory model as you suggested.

 

The compiler options I'm currently using are:

 

-Cs08 -Mb -MMU -TD2LD2LLD2 -WmsgSd4301 -WmsgSd5703

 

so, the memory model is banked and there is no -Fd which matches the options (with the exception of the memory model) in README.TXT.

 

I have tried float and double -- both give 50.124 in sprintf().  Also, formats %f and %lf don't make any difference.

 

I'll try the wizard created project next.

 

0 项奖励
回复

1,499 次查看
CompilerGuru
NXP Employee
NXP Employee

The readme.txt contains one bug, the option for the memory model options for the banked libraries is -mb, not -mt as it states.

-Fd is equivalent to  -TD2LD2LLD2, in fact when I added -Fd in the GUI, the  -TD2LD2LLD2 got automatically added for me.

So if you want to use IEEE32 for double, use ansibfm.lib (note the f).

If you want to use IEEE64, drop the -TD2LD2LLD2 in the command line.

In ANSI-C, floats are promoted to double for function calls with the ellipsis notation, like sprintf, so there is no way to pass a float to sprintf, it always passes a double.

 

Daniel

0 项奖励
回复

1,499 次查看
JBM
Contributor V

I created the project with the wizard and it works.  The compiler options were -Cs08 -MMU -Mb. 

 

I also tried to find what option was giving the -TD2LD2LLD2. option.  I selected each option in the listbox (didn't check it, just selected it) and without changing any options, that compiler option disappeared and now my code works.  Any ideas what caused that?

0 项奖励
回复

1,499 次查看
CompilerGuru
NXP Employee
NXP Employee

No, if you are able to reproduce I would suggest to file a service request for the next person,

just selecting options without checking/unchecking any should not change the existing options.

For -TD2LD2LLD2 note that -cf has the same meaning, so checking/unchecking -cf can affect the -T option.

Anyway, sounds like a separate issue.

 

Daniel

0 项奖励
回复

1,499 次查看
CompilerGuru
NXP Employee
NXP Employee
0 项奖励
回复

1,499 次查看
Lundin
Senior Contributor IV

snprintf is in C99. Codewarrior implements C90.

 

C99 = ISO 9899:1999.

C90 = ANSI/ISO 9899:1900.

 

Very few, if any, embedded compilers implement C99.

0 项奖励
回复

1,499 次查看
JBM
Contributor V

I just thought it was odd that the documentation says it's there and it's not.

 

Any ideas on getting sprintf to work?

 

Thanks!

 

Brad

0 项奖励
回复

1,499 次查看
JBM
Contributor V

I also tried the ANSIBFM.LIB (float is 32 bits, double is 64) and got the same results.

0 项奖励
回复