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 ************************ -------