Info-IBMPC@C.ISI.EDU (Info-IBMPC Digest) (07/31/87)
Info-IBMPC Digest Thursday, July 30, 1987 Volume 6 : Issue 53
This Week's Editor: Phyllis O'Neil
Today's Topics:
TurboC Bug Replies (7 messages)
Re: MS C Compiler V 4.00 Problem
Kaypro --> PC Disks (2 messages)
8085 to 8086 Assembler Translator (2 messages)
Re: Request for Roundoff Constant
----------------------------------------------------------------------
INFO-IBMPC BBS Phone Numbers: (213)827-2635 (213)827-2515
------------------------------
Date: Thu, 23 Jul 87 12:34:15 edt
From: John P. Nelson <decvax!genrad!panda!teddy!jpn@ucbvax.Berkeley.EDU>
To: ucbvax!C.ISI.EDU!Info-IBMPC
Subject: TurboC Replies
This is a reply to two queries in Digest #52 about TurboC. The first
(from J Law), is NOT a TurboC bug, it is a programming error. The code
in question was:
{
double a, b;
scanf("%g %g", &a, &b);
...
The scanf format is incorrect. %g can only be used with variables of
type "float". To read a "double" you must modify the format with an
'l' (for long) character. This is not necessary in printf, where you
pass the floating point value itself, because "float"s are promoted to
"double" when passed as a parameter. Because you are passing the
ADDRESS of the floating point object, C does not have any way to
promote/demote the size of the number. So the scanf line SHOULD read:
scanf("%lg %lg", &a, &b);
---------
The second query, from Esmail Bondakdarian, IS a TurboC bug, and there
is no patch currently available. The code in question is:
main()
{ float a, b;
...
operate(a,b)
}
operate(a,b)
float a,b;
Since this program uses old-style function delarations, the floating
point parameters to "operate" are promoted to "double" before the
function call. This is correct behavior. The BUG is in the code
generated for the "operate" function. Again, because an old-style
function declaration is used, the "float" parameters should be
adjusted to be "double" (See K&R Appendix A "External function
definitions"). The confusion is easy to understand, since if the
function was declared using the new-style ANSI format, then a
prototype would be necessary, and the parameter types would REALLY be
"float", not "double".
Until Borland comes up with a fix for this one (don't hold your
breath), the workaround is simple. Either declare the parameters to
"operate" as "double" (The compiler should be doing this FOR you), or
use new-style function declarations, and insert a function prototype
before "operate" is invoked.
John P. Nelson
decvax!genrad!teddy!jpn
seismo!mit-eddie!genrad!teddy!jpn
ARPA!talcott!panda!teddy!jpn
------------------------------
Date: Thu, 23 Jul 87 11:37:17 PDT
From: rss%ucscf.UCSC.EDU@ucscc.UCSC.EDU (95008000)
To: Info-IBMPC@C.ISI.EDU
Subject: Alleged Turbo C Bugs
Two alleged Turbo C bugs were posted. They are not bugs.
The message from J. Law noted that scanf can read a float with
"%g" but not a double. This is correct. The scanf function has
no way of knowing what type of address you are passing to it
unless you tell it. You can read a double with "%lg". All other
C compilers work this way.
The message from Esmail Bonakdarian has to do with function
taking float parameters, as in
operate( a, b)
float a, b;
Programs written this way demonstrate an incompatibility between
K&R C and ANSI C. According to K&R, all function arguments are
doubles. Compilers allow you to declare an argument float, but
they treat the argument as double. According to ANSI C, function
arguments can be either float or double. If a function is called
without an ANSI prototype, then float arguments are coerced to
double.
Bonakdarian's program does indeed work on MS C 4.0, but only because
it is *not* and ANSI-conforming compiler. It treats function
arguments as double even if they are declared as float. You can see
this by running a program like:
foo(x)
float x;
{ printf("Type number: "); scanf("%f",&x);
printf(" = %f",x);}
Such a program will work under Turbo C but not MS C.
If you want to write portable C programs using real parameters,
you have two choices.
1. [K&R Style] Declare all of your function arguments double,
since a K&R compiler will make them all double anyway.
2. [ANSI Style] Use function prototypes. Make sure every
function call is preceded by a prototype so the compiler will do
argument checking. (The Turbo C swith "-w" will enforce this.)
Roger Schlafly
Borland
------------------------------
Date: Fri, 24 Jul 87 11:49:07 EDT
From: Peter Allsop (Dept. of Chemical Eng.) <ALLSOP%WATACS.BITNET@wiscvm.wisc.edu>
To: Info-IBMPC@C.ISI.EDU
Subject: Re: TurboC "Bug"? Query
PHYJLAW%UOGUELPH asked:
>... Maybe it's the scanf function which can't handle "double"?
You're close... scanf can handle double, but only if you tell it
that you are passing it a pointer to a double. Pointers are always
a (system dependant) fixed length, regardless of what type of variable
they point to (after all, a pointer is just a memory location). Floats
are always pushed onto the stack as doubles, so printf and the like
don't require any special flags for long variables. For functions like
scanf, however, you are pushing pointers, so you have to flag them as
long. Your manual should tell you how to do this under the fscanf
function, but a common way is to prefix the format type with an 'l'.
This would make your scanf line:
scanf("%lg %lg",&a,&b);
Peter Allsop
Biochemical Engineering Group
Department of Chemical Engineering
University of Waterloo
PS: You would have to use the 'l' prefix for any long variable.
A long integer would be read as %ld for example.
------------------------------
Date: Mon, 27 Jul 87 13:56:29 EDT
From: John Owens <john@xanth.cs.odu.edu>
To: INFO-IBMPC@C.ISI.EDU, bonak@cs.uiowa.edu
Subject: Re: (Yet Another) Turbo C Bug?
> { float a,b;
...
> operate(a, b);
> }
>
> operate( a, b)
> float a, b;
In C, floats are always passed as doubles. A nice compiler will take
your format parameter declaration of "float" in operate and handle
this situation for you, but apparently Turbo C does not. You should
declare operate as
operate( a, b)
double a, b;
To decide if this is a bug in Turbo C or not, you'll have to check
whatever standard they are claiming for C (probably K&R) to see
whether the conversion back to float (or forcing the variables to
double) in the called routine is required or optional.
John Owens Old Dominion University - Norfolk, Virginia, USA
john@ODU.EDU old arpa: john%odu.edu@RELAY.CS.NET
+1 804 440 4529 old uucp: {decuac,harvard,hoptoad,mcnc}!xanth!john
------------------------------
Date: Sun, 26 Jul 87 10:19:15 CDT
From: Esmail Bonakdarian <bonak%cs.uiowa.edu@RELAY.CS.NET>
To: INFO-IBMPC-REQUEST@C.ISI.EDU
Subject: Turbo "Bug" Explanation
i had a similar problem but solved it in the following way. instead of
using %g (or %e) i used %lg (or %le). see the reference guide page
201, it took me a long time to find this information.
the program below works on my machine.
esmail bonakdarian
main()
{
/* same as the original that did not work with the */
/* exception that %lg is used in scanf rather than %g */
double a,b,ratio,prod;
printf("Enter 2 numbers: ");
scanf("%lg %lg",&a,&b);
ratio = a/b ;prod=a*b;
printf("Ratio is %g product is %g\n",ratio,prod);
}
------------------------------
Date: Mon, 27 Jul 87 13:11:10 edt
From: neoucom!wtm@seismo.CSS.GOV (Bill Mayhew)
To: info-ibmpc@c.isi.edu
Subject: Turbo C Floating Point Bug
In issue #52, Esmail Bonakdarian points out that Turbo C goofs up
when passing floating point arguments to subroutines. This is
apparently caused by inadvertant coversion of the parameters to
double before passing the values. I seem to recall from somewhere
in K&R that if not stated explicitly, that passed parameters are
cast as double or something to that effect. (My major job function
is *not* C programming, so sorry for any fuzzyness on the above.)
Apparently, tc doesn't completely follow the specification. For the
moment, the following will produce the desired results:
main()
{
float a,b;
a = b = 1;
printf("Enter two numbers: ");
scanf("%f %f", &a, &b);
printf("You entered %4.2f %4.2f.\n", a, b);
printf("In main: %4.2f %4.2f = %4.2f\n", a, b, a*b);
operate(a, b);
}
operate(double a, double b)
{
printf("In sub: %4.2f %4.2f = %4.2f\n", a, b, a*b);
}
Running the program:
C:\TURBOC>mult
Enter two numbers: 3 4
You entered 3.00 4.00.
In main: 3.00 4.00 = 12.00
In sub: 3.00 4.00 = 12.00
C:\TURBOC>
Bill Mayhew
Division of Basic Medical Sciences
Northeastern Ohio Universities College of Medicine
Rootstown, OH 44272-9989 USA phone: 216-325-2511
(wtm@neoucom.UUCP ...!cbatt!neoucom!wtm)
------------------------------
Date: Wed, 29 Jul 87 21:07:11 ADT
From: <REGE210%DAL.BITNET@wiscvm.wisc.edu>
Subject: More on Turbo C Bugs
To: <INFO-IBMPC@C.ISI.EDU>
I have been exploring the recent discussion of bugs
in Turbo C and have discovered several things.
I tried to patch my version of Turbo C according to
the patches published in V6 #50 of Info-IBMPC and discovered
that the my copy of Turbo C is *not* the same as the one
which the patches apply to. This became evident when I
did everything correctly and got different original values
while I was supposed to be entering the patch values. I
didn't change anything.
This implies that Borland is fixing these bugs *VERY*
rapidly. As my version number is 1.0, it also seems to
imply that Borland does not consider bug fixes to be
new versions. This really impresses me as many major
software companies seem to charge a fee for "updates"
which are really bug fixes. Well done guys!
The following program was posted here with a question
as to whether or not it was a bug:
main()
{ float a, b;
a = b = 1;
printf("Enter two numbers: ");
scanf("%f %f", &a, &b);
printf("You entered %4.2f %4.2f.\n", a, b);
printf("%4.2f * %4.2f = %4.2f\n\n", a, b, a * b);
operate(a,b);
}
operate(float a, float b)
{
printf("in sub:\n%4.2f * %4.2f = %4.2f", a, b, a * b);
}
The output from this program was reported as being
(in part):
in sub: 0.00 * 2.12 = 0.00
Sad to say, but I get this as well. The following program
provides a way to work around this by passing pointers
rather than explicit values:
main()
{
float a;
float b;
a = b = 1;
printf("Enter two numbers: ");
scanf("%f %f", &a, &b);
printf("You entered %4.2f %4.2f.\n", a, b);
printf("%4.2f * %4.2f = %4.2f\n\n", a, b, a * b);
operate(&a,&b);
}
/* Originally, this code received its arguments
by value, not reference. It did not work. Passing
the arguments by reference instead of value works. */
operate( float *a, float *b)
{
printf("in sub:\n%4.2f * %4.2f = %4.2f", *a, *b, *a * *b);
}
Does anybody have a fix for this problem? If so, please
post it ASAP! Many thanks!
This program was also reported as a bug:
struct
{
int e:15;
} t;
main()
{
t.e = 0;
t.e +=1;
t.e++;
}
I see nothing wrong with this, and I get a fatal
compiler error (Irreducible Expression Tree) as reported.
Anybody know of a fix for this one?
The last problem I saw does not appear to be a bug
but I could be mis-reading my documentation (which is
vague on this point). This is the program:
main()
{
double a,b,ratio,product;
printf("Enter 2 numbers: ");
scanf("%g %g",&a,&b);
product=a*b;
ratio=a/b;
printf("Ratio is %g product is %g\n",ratio,product);
}
It is reported to bomb out with an Underflow error
message at runtime and I got this message the first time
I ran the program. Further investigation revealed two
problems:
1 - The author was entering 10.0,3.0 at the prompt.
Notice there is no comma between the specifiers
in scanf. If the comma is included in the input
but left out of the description string passed to
scanf you *should* get some kind of error message.
See page 148 of Kernighan and Ritchie.
2 - This is where the documentation (all sources I
have) gets vague. If you make no other
changes than changing %g to %G in scanf and
enter 10.0 3.0 (not 10.0,3.0) the program
works correctly. The Turbo C reference manual
mentions %G in passing on page 199 but no where
that I can find does it actually say what %G
is. Page 62 of The C Programmer's Handbook
Published by AT&T Bell Laboratories says that
f, e, and g are equivalent, but doesn't say
much about G. Here is the working program:
#include<stdio.h>
main()
{
/* This program was initially listed as giving an underflow error
message. It did this to me the first time I tried it and them
it changed to a domains error. I'm not sure why.
Changing the scanf definition from %g to %G worked however. */
double a,b,ratio,product;
printf("Enter 2 numbers: ");
scanf("%G %G",&a,&b);
product=a*b;
ratio=a/b;
printf("Ratio is %g product is %g\n",ratio,product);
}
Does anybody know if the #include<stdio.h> must
be include for reasons other than form? What about
other include files?
If anybody else can throw more light on this
please post a message here. I am just learning C
so maybe a person who is more experienced with C
can provide us with more data.
John Robinson
------------------------------
Date: Thu, 23 Jul 1987 18:40 EDT
From: LENOIL@XX.LCS.MIT.EDU
To: "Joshua D. Males" <josh%ILJCT.BITNET@WISCVM.WISC.EDU>
Cc: Info-IBMPC@C.ISI.EDU
Subject: Re: MS C Compiler V 4.00 Problem
... I started recently to work with the Microsoft C compiler V 4.00,
but, unfortunately, when I tried to use the library function "printf",
the linker (MS V 3.05) claimed that "printf" is an invalid object code.
the same error was encountered when I tried to compile with the /Zi option,
even for the minimal program: main(){}...
Could you help me find out what is the problem?
-----
You were using an older version of LINK, perhaps one that came with
DOS or another MS language product. C 4.0 comes with LINK version
3.51; use it.
------------------------------
Date: Thu, 23 Jul 87 10:49:16 EDT
From: Jim.Moore@WB1.CS.CMU.EDU
To: rbw@cs.williams.edu
Subject: Kaypro --> PC Disks
Cc: info-ibmpc@c.isi.edu, jm6m@andrew
I use Media Master, and it works just fine.
There is one problem, however. In the case of kaypro 4/10 disks, it seems as
though MM can't handle disks FORMATTED ON THE KAYPRO. However, if you format
them with MM (for the K-10/4), then both machines can use them just fine.
Good Luck.
Jim Moore
(IBM Artificial Intelligence Liaison for Carnegie Mellon University)
------------------------------
Date: Fri, 24 Jul 87 08:05:45 edt
From: jkerby@nswc-wo.ARPA
To: rbw@cs.williams.edu
Subject: Re: Kaypro -> PC Transfer
Cc: info-ibmpc@c.isi.edu
In response to your request for a program to read floppies from a Kaypro
CP/M machine and convert them to PC format, I would suggest "Media Master"
from Intersecting Concepts, Inc. The last address I have is
4573 Heatherglen Ct.
Moorpark, CA 93021
(805) 529-5073
It's about a year old but may still be good. I have used the program on a
Zenith 158 and a Zenith 248 successfully. It supports SEVERAL formats and
is relatively cheap (~$40). Hope this helps.
Fred Kerby (jkerby@nswc-wo.arpa)
------------------------------
Date: Thu 23 Jul 87 17:17:43-PDT
From: Bob Knight <KNIGHT@SRI-NIC.ARPA>
Subject: 8085 to 8086 Assembler Translator Needed
To: info-ibmpc@C.ISI.EDU, info-micro@BRL-VGR.ARPA
Anyone know of one available on the net? I'm in desperate need of
one. Please reply to this accounts.
Thanks in advance,
Bob
------------------------------
Date: Fri 24 Jul 87 10:29:11-EDT
From: Gern <GUBBINS@RADC-TOPS20.ARPA>
Subject: Re: 8085 to 8086 Assembler Translator?
To: KNIGHT@SRI-NIC.ARPA
cc: info-ibmpc@C.ISI.EDU, info-micro@BRL-VGR.ARPA
Yes, I believe I have a PD one, written (I believe) at Clarkson
by a student. It is in Zenith Z-100 ZBASIC which should run directly
under IBMPC GWBASIC (BASICA). I have never tried it. If you want
it, flag me and I will upload it.
Cheers,
Gern
------------------------------
Date: Fri, 24 Jul 87 11:48:14 EDT
From: Peter Allsop <ALLSOP%WATACS.BITNET@wiscvm.wisc.edu>
To: Info-IBMPC@C.ISI.EDU
Subject: Re: Request for Roundoff Constant
Gloria Wren <wren@BRL.MIL> asked:
>I need to set a machine round-off constant for a public domain code
>called Episode from Lawrence Livermore Lab. The code is the older
>version of what is today known as DGEAR, an ODE integrator...
>Does anyone
>know the correct value for an IBM-AT or any way to determine it since
>neither value above works? ...
Based on the value of UROUND quoted for an IBM-360/70, the
technical term for the number you are after is the 'Machine Epsilon'
(Em), sometimes called the Machine Precision. It is defined as the
smallest number which you can add to X and get a number not equal to
X. It is related in a complex way to the format used by the computer
when it stores numbers, and should really be calculated based on this
representation. You can get an approximate value using the following
program (in fortran, which I assume you are using):
EM 00010
IMPLICIT REAL*4 (A-H,O-Z) EM 00020
X = 1 EM 00040
IX = 1 EM 00050
DO 1000 I=1,1000 EM 00060
IX = IX*2 EM 00070
DX = 1./IX EM 00080
DX = X + DX EM 00090
IF(DX.EQ.X)GOTO 2000 EM 00100
1000 CONTINUE EM 00110
WRITE(6,1100) EM 00120
1100 FORMAT(' Loop terminated by counter') EM 00130
STOP EM 00140
C EM 00150
2000 IX = IX/2 EM 00160
DX = 1./IX EM 00170
WRITE(6,2100)IX,DX EM 00180
2100 FORMAT(' Em = 1/',I10,' = ',1PD10.3) EM 00190
STOP EM 00210
END EM 00220
A few comments:
- The use of integers vs reals in the above is quite intentional, as
is the use of an iterative multiply rather than power.
- The 80287 has several methods of rounding available. You should
treat the value of Em from the above as a limiting lower limit.
Your DGEAR-like program may run better with a slightly larger value
- Of course Em changes with the precision used (REAL*8 vs REAL*4)
and the hardware (with vs without 80287). The value cited for an
IBM-360/370 is for single precision (REAL*4), so if the program
you are converting is all double precision you know that they
are really after a limiting case. This is not uncommon.
- My reference on this sort of stuff is:
'Numerical Methods, Software and Analysis - IMLS Reference Edition'
by John R. Rice
(McGraw-Hill, Toronto; 1983)
- see chapter 3
Peter Allsop
Biochemical Engineering Group
Department of Chemical Engineering
University of Waterloo
------------------------------
End of Info-IBMPC Digest
************************
-------