C Programming Language Kernighan Ritchie Examples

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
jonesypeter
New member
Posts: 9
Joined: Thu Jun 16, 2016 7:16 pm

C Programming Language Kernighan Ritchie Examples

Post by jonesypeter »

Hi,

I used C when I was at College some 30 years ago (I know I don't look that old!), and recently thought I would give it a go again. I'm using the above book, but am having trouble getting examples to work on z88dk which compile fine using the standard Linux compiler or mingw on Windows.

For example:

Code: Select all

#include <stdio.h>
main()
{
float fahr, celsius;
int lower, upper, step;
 
lower = 0;
upper = 300;
step = 20;
 
fahr = lower;
while (fahr <=upper) {
        celsius = (5.0/9.0) * (fahr-32.0);
        printf ("%3.0f %6.1f\n", fahr, celsius);
        fahr = fahr + step;
}
}
The main thing I have learnt so far with Z88dk (and thanks to AA for all his install help), is put a line return at the end of your code.

I'm compiling with the Classic version and just using:

Code: Select all

zcc +zx -vn -lm test.c -o test -lndos -create-app
When I run it, I just get these errors which I have put into PasteBin:

http://pastebin.com/mSWwgy0v

I did somehow manage to get it to run once, but I can't for the life of me remember how, but upon running in via the emulator, I just got this (which seems to display the formatting rather than the values). I have tried looking through other examples to see what is wrong, but without success:

https://s32.postimg.org/vnkq05y9h/z88dk.jpg

Thanks in advance
jonesypeter
New member
Posts: 9
Joined: Thu Jun 16, 2016 7:16 pm

Post by jonesypeter »

Sorry, image should be as follows. Seems to be no way to edit posts?

Image
jonesypeter
New member
Posts: 9
Joined: Thu Jun 16, 2016 7:16 pm

Post by jonesypeter »

Ignore the bit about the compile errors. Sorted that. Its just the screen display output that's the issue. Thanks
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

I will add a bit more in the next post. The edit has button has been removed because it frequently causes forum crashes.

The sccz80 (z88dk's native c compiler) scans printf strings to find out how small a printf implementation can be used. If the program doesn't print or scan floats and longs, sccz80 makes a note of that and the crt will cause a smaller version of printf to be used in order to reduce the program size. In this case, it's making a mistake so we have to tell the crt that we want the full blast float printf.

zcc +zx -vn -lm test.c -o test -lndos -create-app -pragma-define:floatstdio

This is a bug in sccz80 so maybe dom will have a look at this a little later. If your install is more than a few days old, the colon in the pragma may have to be replaced with an = sign (I like the colon better :)
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

K&R is still the best C book IMO, I have a copy right over there and I remember doing that exercise while in school too :)

With small micros, the level of standards compliance of compilers and libraries vary due to limitations in the compilers or limitations in the target (particularly memory limitations). Most 8-bit compilers are very weak on the library end and often aim at implementing a small subset of the C standard library that is most used in embedded applications. z88dk is different in that regard -- its library is fairly complete but there are still things missing. On the compiler side, compliance refers to what language features are supported. z80 compilers vary from weak standards compliance (mainly early small c implementations), to medium compliance (z88dk's sccz80 is an example) to near full compliance (sdcc is probably by itself in this category).

K&R ansi edition is using C89 which will mostly be supported by sccz80 and sdcc. You can read a little bit about compiler compliance here: http://www.z88dk.org/wiki/doku.php?id=t ... compliance This is not an exhaustive list but a list of the most notable shortcomings.

Also important is knowing data type sizes: http://www.z88dk.org/wiki/doku.php?id=t ... data_types
C allows the compiler to decide how any bits are allocated for each type and compilers will choose sizes that the underlying target can efficiently implement. So, for example, on a z80 an int will be 16-bits because it has some 16-bit characteristics which makes ints of that size fairly fast. On an x86 int will be 32- or 64-bit. Programs written for 32-bit ints may not work with the z80's 16-bit ints because the 16-bit int doesn't have as large a range. As long as you are aware of this as programs are written, you will be ok. The new standards have introduced types int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t and uint64_t in stdint.h that define types with their sizes in their names to increase portability of programs.

Within z88dk we have two C compilers now and two C libraries. sdcc is the most standards compliant C compiler and it can be used with the new C library and soon with the classic one as dom is working feverishly on that. sdcc will tend to generate faster code than sccz80 and at one time it also generated larger code but that is not always the case anymore; for code that uses a lot of floats and longs, sccz80 will still tend to be smaller. The new C library has been written from scratch aiming at a subset of C11 compliance but it is still missing disk io. The classic C library has a simpler stdio that is smaller and does support some disk systems.

Anyway I mention these things because if you are following K&R, you should know why things might not work as expected. If you want the maximum compliance combination, that would be sdcc + the new c library as long as you don't need file i/o.


I noted from the test program here that the output formats for %f are not correctly formatted. It looks like the classic c lib may be ignoring the width specifier for %f. I compiled the same for the new c lib and that one too seems to do the %f formatting incorrectly (and the new c lib is supposed to do it all correctly), doing it like %g for the decimal portion. So that is something I will have to look into.
jonesypeter
New member
Posts: 9
Joined: Thu Jun 16, 2016 7:16 pm

Post by jonesypeter »

Thanks Alvin, for such a detailed explanation. I will look at these links you provided, and try compiling with the new c library. Best wishes
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

In this case, it's making a mistake so we have to tell the crt that we want the full blast float printf.

zcc +zx -vn -lm test.c -o test -lndos -create-app -pragma-define:floatstdio

This is a bug in sccz80 so maybe dom will have a look at this a little later.
dom added a fix to the June 18 build.
jonesypeter
New member
Posts: 9
Joined: Thu Jun 16, 2016 7:16 pm

Post by jonesypeter »

I downloaded last nights build and can confirm that the fix has worked and I can now compile with:

Code: Select all

zcc +zx -vn -lm test.c -o test -lndos -create-app
Thank you

As we discussed the other day it seems like the %3.0f (At least three characters wide, no decimal point, and no fraction digits) is not working as it should be.

I have added some very subtle(!) colouring.

Image

Code: Select all

#include <stdio.h>
#define INK     7
#define PAP     3
#define FLA     0
#define BRI     1
#define INV     0
#define BOR     4
#define COL     128*FLA+64*BRI+8*PAP+INK

static void main(void);
static void setup(void);
void main(void)
{
float fahr, celsius;
int lower, upper, step;
setup();

lower = 0;
upper = 300;
step = 20;
fahr = lower;
printf("Conversion of Temperature\n\nBrian Kernighan & Dennis Ritchie\n\n");
while (fahr <=upper) {
        celsius = (5.0 / 9.0) * (fahr-32.0);
        printf ("%3.0f %6.1f\n", fahr, celsius);
        fahr = fahr + step;
        }

}
void setup(void)
{
     #asm
     // Sets default ink and paper colour, then clears screen
     ld a,COL
     ld (23693),a
     call 3503
     // Sets border colour
     ld a,BOR
     call 8859
     #endasm
}
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

%aefg floating point formatting should be fixed for the new c library only in the June 27 build
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

For reference, the .0 case was fixed up in classic last week - 0 ended up being the default for no precision defined!
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

I tried it and confirm it works correctly in the classic build now too. I thought something non-cosmetic would have to be done to fix that.
Post Reply