3

I'm attempting to compile a program in C for the ZX Spectrum using Z88DK. However, I'm facing an issue when trying to use printf to print out the value of a float.

The code I'm trying to compile:

#include <stdio.h>
#include <math.h>

int main()
{
    printf("Hello World\n");
    printf("Testing float...\n");
    double pi = 3.141;
    printf("Pi is: %f\n", pi);
    return 1;
}

and I'm compiling with:

zcc +zx -lm -create-app -startup=1 -clib=new  main.c -o floatTest

The program compiles however nothing is printed on the screen where the value of the float should be. Here is a screenshot of the Fuse emulator output of the program above.

Fuse emulator screenshot of output of program above

I've tried using float and double, adding different formatting options like %06.2f, but nothing seems to work. I can't get anything to display on the screen.

I'm stuck on how to resolve this issue and any help would be appreciated!

9
  • 1
    Does the hardware actually have an FPU? If not, have you enabled any emulation layer when compiling the program?
    – Ruslan
    Commented Feb 25, 2020 at 12:53
  • 1
    @Ruslan, not a porblem with missing FPU (which is very rare in Z80 systems). The math lib should handle the floating point calculations without extra hardware.
    – UncleBod
    Commented Feb 25, 2020 at 13:09
  • 4
    @cobbm: You have checked that you can print int with %d, char with %c and string with %s, haven't you? Checking that other parts of printf work is wise before you get into floats. Commented Feb 25, 2020 at 13:33
  • 3
    I don't know about that specific platform, but in the toolchain for the ARM-based MCU that I'm writing code for right now, I have an option to enable "floating point printf" or not. If I choose the "not" option, then the %...f printf directive behaves exactly as you describe: It consumes one float-size argument, and it outputs nothing at all. Maybe your library works the same way. Maybe you even have the same option somewhere. Commented Feb 25, 2020 at 15:03
  • 1
    Various compilers do not print FP well unless some FP math is done. Try double pi = 3.141; double m = pi/100.0; printf("Pi is: %f\n", pi); or other such code. Commented Feb 25, 2020 at 15:31

5 Answers 5

12

Assuming you use the SDCC backend: SDCCs printf does not include float support by default. You need to recompile the z80.lib library with USE_FLOATS=1 set in printf_large.c

6

With newlib it seems you have to explicitly state that you want to include the floating point formatter with a pragma, just add:

#pragma printf %f

to the source code. That way it will work with both sccz80 and zsdcc as the compiler. By default the integer converters are included.

sccz80 does format detection, but this is only picked up the classic library. So if you want to use zsdcc and classic you'll have to specify them again.

Likewise for scanf the set of converters can be configured using

#pragma scanf converters

There's some documentation on z88dk wiki here: https://github.com/z88dk/z88dk/wiki/Classic--Pragmas#configuring-printf-and-scanf-converters

4

The z88dk does not differentiate between float or double, at least with its own compiler; the SDCC backend is another beast.

Some years ago I played around with the z88dk, targetting the ZX81. I was kind of disappointed that its implementation of printf() does not support floating point data types. It might have changed in the meantime, but I'm afraid that rather not. A quick look through the Wiki does not reveal anything, even though you might like to check this yourself.

Actually there are different implementations of printf(). The compiler decides by introspection of your source which one to use.

0

Although the printf implementation z88dk's classic C library doesn't support outputting floats, it does have in its stdlib.h a mostly undocumented function named ftoa that will convert a float to a string:

https://github.com/z88dk/z88dk/blob/master/libsrc/math/genmath/ftoa.c

5
  • Classic has actually supported printing floats for around 20+ years. As it happens, that ftoa() routine (and the corresponding ftoe()) are the routines that are used internally. The format handler is here: github.com/z88dk/z88dk/blob/master/libsrc/stdio/… which is a bit spaghetti-like due to supporting the two different argument passing conventions and the 3 different float sizes currently supported.
    – suborb
    Commented May 22, 2020 at 22:14
  • @suborb perhaps, but it doesn't work for me. Using the %f specifier just prints a literal "f" character in the output, no matter what value I supply in the documented pragma. Commented May 24, 2020 at 19:32
  • Don't suppose it's a multi-file project? In which case this thread explains how to sort it out: z88dk.org/forum/viewtopic.php?pid=18615#p18615 if not, raise an issue and I'll get it sorted.
    – suborb
    Commented May 25, 2020 at 20:17
  • @suborb It is, and I'm also using --no-crt as I'm working with a custom memory layout. I tried the instructions on the forum but those didn't work for me either Commented May 28, 2020 at 19:55
  • 2
    You're well off-piste using a custom CRT. No wonder it's not working as intended! You'll need to take a copy of libsrc/stdio/__printf_format_table.asm and add to your project after editing it to include the formatters you need. The standard CRTs handle it automatically via lib/crt/classic/crt_runtime_selection.asm
    – suborb
    Commented May 29, 2020 at 20:17
-1

The zx81 fp support is complete since.. very long time! Printf %f works a well. On a Spectrum there is plenty of fp libraries you can choose, varying in precision and size, including a shortcut to the ROM ones. The same shortcut is available on the zx81.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .