alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) (01/12/91)
The following program demonstrates a printf that doesn't seem to work
properly when compiled using a variety of C compilers for an 8086 machine.
The program is as follows:
-----------------------------//---------------------------
#include <stdio.h>
main()
{
int x,y;
x = 65536/512;
y = 512;
printf("This works : %d, %d\n",x,y);
printf("This doesn't work : %d, %d\n",65536/512,512);
}
----------------------------//------------------------------
And here is a sample output:
This works : 128, 512
This doesn't work : 128, 0
Does anyone have any idea why?
Is this a problem with my machine or the printf routine?
ekalenda@cup.portal.com (Edward John Kalenda) (01/12/91)
> The following program demonstrates a printf that doesn't seem to work > properly when compiled using a variety of C compilers for an 8086 machine. > The program is as follows: > > #include <stdio.h> > main() > { > int x,y; > x = 65536/512; > y = 512; > printf("This works : %d, %d\n",x,y); > printf("This doesn't work : %d, %d\n",65536/512,512); > } > And here is a sample output: > This works : 128, 512 > This doesn't work : 128, 0 > > Does anyone have any idea why? > Is this a problem with my machine or the printf routine? The problem is that 65536/512 results in a LONG being pushed on the stack so the send %d gets the high word of the long, which is zero. The reason it works in the first case is that the long result is converted to an int when assigned to the int x. I use MSC 6.0 with /X4 to catch oddities like this at compile time. Most UNIX programmers run into this when moving from the 32 bit machines to DOS. Ed ekalenda@cup.portal.com
torvalds@cs.Helsinki.FI (Linus Torvalds) (01/12/91)
In article <3577@bruce.cs.monash.OZ.AU> alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) writes: > >The following program demonstrates a printf that doesn't seem to work >properly when compiled using a variety of C compilers for an 8086 machine. >The program is as follows: >-----------------------------//--------------------------- > >#include <stdio.h> > >main() >{ > int x,y; > x = 65536/512; > y = 512; > printf("This works : %d, %d\n",x,y); > printf("This doesn't work : %d, %d\n",65536/512,512); >} > >----------------------------//------------------------------ > >And here is a sample output: > >This works : 128, 512 >This doesn't work : 128, 0 > >Does anyone have any idea why? >Is this a problem with my machine or the printf routine? This is NOT a bug, but a programming error :-). The 65536 is implicitly converted to a long (ie 65536L), as it doesn't fit into a int on the 8086 (all 8086 c-compilers I've used use 16-bits ints, but on a 32 bit int machine this works as "expected"). Thus 65536/512 is a LONG, not an int and is sent to printf as such. The reason 'x=65536/512;printf(..,x,) works is that 65536/512 is (implicitly) converted to an int by the assignment into x. The code works if you change the second printf to: printf("%d %d",(int) (65536/512),512); or alternately: printf("%ld %d",65536/512,512); NOTE! Please make 65536 EXPLICITLY long by using 65536L, this makes the code much clearer and portable. (or don't use machines with a 16 bit int :-) Linus "mostly wrong" Torvalds torvalds@cs.helsinki.fi
mbryan@netcom.UUCP (Michael Bryan) (01/13/91)
In article <3577@bruce.cs.monash.OZ.AU> alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) writes: [Program which gives unexpected results:] >#include <stdio.h> >main() >{ > int x,y; > x = 65536/512; > y = 512; > printf("This works : %d, %d\n",x,y); > printf("This doesn't work : %d, %d\n",65536/512,512); >} >And here is a sample output: >This works : 128, 512 >This doesn't work : 128, 0 The problem is that in the printf statement, 65536/512 is a long integer, and gets passed to printf as to 4 bytes, not 2. Your format control says expect two 2-byte integers, so the higher-order bytes of the longword get interpreted as the second integer, and they are zero. If you changed your printf control to "%ld, %d", you would see the correct answer. (Or perhaps more revealing, change it to "%d, %d, %d", to see "128, 0, 512" printed.) Yet another alternative would be to cast the constant before passing to printf, as in "(int)(65536/512)". The reason is that the compiler sees 65536 as requiring a longword (max short integer is 65535, unsigned), so the type of the constant 65536 is a longword. The constant 65536/512 is a long divided by a short, which will also have a type of long, due to C's type-conversion rules. The reason "x = 65536/512" works is that the long constant "128" is converted back to a short integer before storing the value in "x". The first call to printf then passes two bytes for "x", and it prints as expected. As far as I know, this is completely proper behaviour for C. I'm not sure if all 16-bit integer versions of C behave exactly this way, but any I've seen do. -- Mike Bryan (mbryan@netcom, {claris,apple}!netcom!mbryan) W:408/733-6565 H:408/738-2479 Sunnyvale, CA "Does this sentence remind you of Agatha Christie?"
henry@zoo.toronto.edu (Henry Spencer) (01/13/91)
In article <20722@netcom.UUCP> mbryan@netcom.UUCP (Michael Bryan) writes: >As far as I know, this is completely proper behaviour for C. I'm not >sure if all 16-bit integer versions of C behave exactly this way, but >any I've seen do. All the correct ones do. Some of the more cautious ones warn you about it. -- If the Space Shuttle was the answer, | Henry Spencer at U of Toronto Zoology what was the question? | henry@zoo.toronto.edu utzoo!henry
gwyn@smoke.brl.mil (Doug Gwyn) (01/13/91)
In article <3577@bruce.cs.monash.OZ.AU> alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) writes: > printf("This doesn't work : %d, %d\n",65536/512,512); Of course it doesn't work, you're trying to print a long int using a %d format specification!
Ralf.Brown@B.GP.CS.CMU.EDU (01/13/91)
-- {backbone}!cs.cmu.edu!ralf ARPA: RALF@CS.CMU.EDU FIDO: Ralf Brown 1:129/3.1 BITnet: RALF%CS.CMU.EDU@CMUCCVMA AT&Tnet: (412)268-3053 (school) FAX: ask DISCLAIMER? Did | It isn't what we don't know that gives us trouble, it's I claim something?| what we know that ain't so. --Will Rogers
ark@alice.att.com (Andrew Koenig) (01/14/91)
In article <3577@bruce.cs.monash.OZ.AU> alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) writes: > printf("This doesn't work : %d, %d\n",65536/512,512); > This doesn't work : 128, 0 > Is this a problem with my machine or the printf routine? It's probably a bug in your program. If your compiler stores ints in 16 bits, then 65536 is a long and 65536/512 is also a long. You should therefore do one of the following: printf("This should work : %d, %d\n", (int)(65536/512), 512); printf("This might also work : %ld, %d\n", 65536/512, 512); -- --Andrew Koenig ark@europa.att.com
t-kevinj@microsoft.UUCP (Kevin Johnson) (01/15/91)
In article <3577@bruce.cs.monash.OZ.AU> alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) writes: ...<some stuff deleted here>... > int x,y; > x = 65536/512; > y = 512; > printf("This works : %d, %d\n",x,y); > printf("This doesn't work : %d, %d\n",65536/512,512); ...<more stuff deleted here>... >And here is a sample output: >This works : 128, 512 >This doesn't work : 128, 0 In this case, 65536/512 is going to be considered a long value (remember that an int is 16 bits and a long is 32 on the 8086). In the first case (x = 65536/512 ;), the long is being typecast back to an int. In the printf statement, no typecasting is being done so the compiler is pushing a long rather than an int. When printf is trying to figure out what you want to print, it grabs the low word of (65536/512) to fit the first %d, and the high word (zero, in this case) to fit the second %d. The last word pushed (OK, technically the first one, but that's irrelevant here) is the value 512, which is ignored by printf. To fix this, typecast the 65536/512 in the printf to an int: printf ("This doesn't work : %d, %d\n", (int) 65536 / 512, 512) ; Things will magically work... --Kevin
cur022%cluster@ukc.ac.uk (Bob Eager) (01/15/91)
In article <3577@bruce.cs.monash.OZ.AU>, alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) writes: > The following program demonstrates a printf that doesn't seem to work > properly when compiled using a variety of C compilers for an 8086 machine. > The program is as follows: > -----------------------------//--------------------------- > > #include <stdio.h> > > main() > { > int x,y; > x = 65536/512; > y = 512; > printf("This works : %d, %d\n",x,y); > printf("This doesn't work : %d, %d\n",65536/512,512); > } > > ----------------------------//------------------------------ > > And here is a sample output: > > This works : 128, 512 > This doesn't work : 128, 0 > The compiler sees the 65536 in the second printf, and says: "This can't be represented in an int, I need a long". I wonder if the 'rules' say that it has to do this; certainly for an expression involving variables, the presence of a long in an expression coerces the whole expression to long. Given the above, it is easy to see what is happening. A four byte item is pushed on the stack when printf is called: this represents 6655536/512 as a long. The lower two bytes (the first ones on an 80x86) will contain the 128, and are processed correctly. The second two bytes will be zero, and are printed as the second value. I bet if you change the first %d to %ld in the second printf, the expected answer will appear! -------------------------+------------------------------------------------- Bob Eager | University of Kent at Canterbury | +44 227 764000 ext 7589 -------------------------+-------------------------------------------------
bytehead@bluemoon.uucp (Bryan Price) (02/09/91)
alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) writes: > > -----------------------------//--------------------------- > > #include <stdio.h> > > main() > { > int x,y; > x = 65536/512; // You just assigned a long int to a short int here > y = 512; > printf("This works : %d, %d\n",x,y); > printf("This doesn't work : %d, %d\n",65536/512,512); // Buzzzzt! The first %d should be a %ld, since you are // passing a long int (not a short int) for the 1st numeric // parameter. 65536 is a long, and forces the compiler to // pass it as a long, even if it fits in a short int. > } > > ----------------------------//------------------------------ > > And here is a sample output: > > This works : 128, 512 > This doesn't work : 128, 0 > > Does anyone have any idea why? > Is this a problem with my machine or the printf routine? This is a problem with your mind. #include <.sig>