[comp.lang.c] bug? in turbo c++

rg@msel.unh.edu (Roger Gonzalez) (03/07/91)

the following program demonstrates this "bug":
main()
{
    int     i;
    long    j;

    for (i = 0; i < 1000; i++, j = i*2)
        printf("oh crud: %x %10d %x\r", i, j, i);
}

The third number printed is always zero.  It corrects itself if the
second formatting string is %10ld.  Is this a new ansi-ism?  Will this
behavior change to what my Unix cc fingers expect if I set it to K&R?
Is it a bug?  I can see them arguing that it isn't a bug, but I find
it an unpleasant nonbug at the very least.

-Roger
-- 
"The question of whether a computer can think is no more interesting
 than the question of whether a submarine can swim" - Edsgar W. Dijkstra 
rg@[msel|unhd].unh.edu        |  UNH Marine Systems Engineering Laboratory
r_gonzalez@unhh.bitnet        |  Durham, NH  03824-3525

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (03/07/91)

In article <1991Mar6.173733.430@unhd.unh.edu> rg@msel.unh.edu (Roger Gonzalez) writes:
>     int     i;
>     long    j;
>     for (i = 0; i < 1000; i++, j = i*2)
>         printf("oh crud: %x %10d %x\r", i, j, i);
> The third number printed is always zero.  It corrects itself if the
> second formatting string is %10ld.

This makes perfect sense. On a low level, printf is expecting three
2-byte arguments; you fed it a 2-byte, a 4-byte, and another 2-byte. The
4-byte always has high word 0 since j is smaller than 65536. Numbers are
stored low-byte first on that machine. So the third 2-byte is 0.

If anything were done differently---a noncontiguous stack, or arguments
passed in registers, or a different word order, or whatever---you'd see
different results with the original code.

When you use %10ld, printf knows to expect a long for its second
argument.

> Will this
> behavior change to what my Unix cc fingers expect if I set it to K&R?

You mean ``to what my all-the-world's-a-VAX fingers expect.'' You have
to distinguish properly between ints and longs if you want your programs
to work on machines where int != long.

---Dan

henry@zoo.toronto.edu (Henry Spencer) (03/07/91)

In article <1991Mar6.173733.430@unhd.unh.edu> rg@msel.unh.edu (Roger Gonzalez) writes:
>The third number printed is always zero.  It corrects itself if the
>second formatting string is %10ld.  Is this a new ansi-ism?  Will this
>behavior change to what my Unix cc fingers expect if I set it to K&R?
>Is it a bug? ...

It is not a bug; it is correct behavior.  Printing a long with %d has
always been wrong, and if it worked it was because you were lucky in
your choice of machine and compiler such that it accidentally came
out right.
-- 
"But this *is* the simplified version   | Henry Spencer @ U of Toronto Zoology
for the general public."     -S. Harris |  henry@zoo.toronto.edu  utzoo!henry

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (03/07/91)

In article <1991Mar6.173733.430@unhd.unh.edu>, rg@msel.unh.edu (Roger Gonzalez) writes:
>     int     i;
>     long    j;

>         printf("oh crud: %x %10d %x\r", i, j, i);
> Is this a new ansi-ism?

Nope, that's the way it was back when 'long' became available on PDP-11s.
Always use "%d", "%x" and so on for "int".	(PDP-11: 2 == sizeof (int))
Always use "%ld", "%lx" and so on for "long".	(PDP-11: 4 == sizeof (long))
No need to worry about "char" or "short", as they promote to "int".

> Will this
> behavior change to what my Unix cc fingers expect if I set it to K&R?

This *IS* what UNIX cc compilers require.  You are confusing "machine
where sizeof (int) == sizeof (long)" with "UNIX machine".  'Tisn't so.
PDP-11s & Z8000s running UNIX had the same problem for the same reason.

-- 
The purpose of advertising is to destroy the freedom of the market.

kirste@methan.chemie.fu-berlin.de (Burkhard Kirste) (03/07/91)

rg@msel.unh.edu (Roger Gonzalez) writes:

>the following program demonstrates this "bug":
>main()
>{
>    int     i;
>    long    j;
>
>    for (i = 0; i < 1000; i++, j = i*2)
>        printf("oh crud: %x %10d %x\r", i, j, i);
>}
>
>The third number printed is always zero.  It corrects itself if the
>second formatting string is %10ld.  Is this a new ansi-ism?  Will this
>behavior change to what my Unix cc fingers expect if I set it to K&R?
>Is it a bug?  I can see them arguing that it isn't a bug, but I find
>it an unpleasant nonbug at the very least.
>
Under UNIX, it doesn't matter: int = long = 32 bit (usually),
although you have to specify %hd for short int (16 bit).
Otherwise, if int = 16 bit, long = 32 bit, you have to use
%ld for long. That is simply logical, not a "bug"!
-- 
  |~|   Freie Universitaet Berlin, Institut fuer Organische Chemie
  / \   Burkhard Kirste    kirste@kristall.chemie.fu-berlin.dbp.de
 /FUB\  Takustrasse 3, D-1000 Berlin 33      UUCP: kirste@fub.uucp
 `---'  Telefon: (030)838-6484              Telefax: (030)838-5163

dcurtis@crc.ac.uk (Dr. David Curtis) (03/08/91)

In article <1991Mar6.173733.430@unhd.unh.edu> rg@msel.unh.edu (Roger Gonzalez) writes:
>the following program demonstrates this "bug":
>main()
>{
>    int     i;
>    long    j;
>
>    for (i = 0; i < 1000; i++, j = i*2)
>        printf("oh crud: %x %10d %x\r", i, j, i);
>}
>
>The third number printed is always zero.  It corrects itself if the
>second formatting string is %10ld.  Is this a new ansi-ism?  Will this
>behavior change to what my Unix cc fingers expect if I set it to K&R?
>Is it a bug?  I can see them arguing that it isn't a bug, but I find
>it an unpleasant nonbug at the very least.
>

Of course this isn't a bug. The only way it could possibly work as you
apparently intend if int and long were the same size. You seem to expect
printf() to know the size of the arguments which have been put on the
stack, but of course the only  way for it to do this is by providing if
with a (correct) format string.

Dave Curtis

Academic Department of Psychiatry,    Janet:       dc@UK.AC.UCL.SM.PSYCH
Middlesex Hospital,                   Elsewhere:   dc@PSYCH.SM.UCL.AC.UK
Mortimer Street, London W1N 8AA.      EARN/Bitnet: dc%PSYCH.SM.UCL@UKACRL
Tel 071-636 8333 Fax 071-323 1459     Usenet: ...!mcsun!ukc!mrccrc!D.Curtis

ch@dce.ie (Charles Bryant) (03/10/91)

In article <1991Mar6.173733.430@unhd.unh.edu> rg@msel.unh.edu (Roger Gonzalez) writes:
>main()
>{
>    int     i;
>    long    j;
>
>    for (i = 0; i < 1000; i++, j = i*2)
>        printf("oh crud: %x %10d %x\r", i, j, i);
>}

Surely I am not the only person to notice that j is used before being
set? (On the first pass only). Maybe our newsfeed is just clogged.
-- 
Charles Bryant (ch@dce.ie)
--
If you like the opinions expressed in this message, they may be available
for rent - contact your local sales office. Low interest deals available.

boyd@necisa.ho.necisa.oz.au (Boyd Roberts) (03/11/91)

In article <DDTO3BF@methan.chemie.fu-berlin.de> kirste@methan.chemie.fu-berlin.de (Burkhard Kirste) writes:
>Under UNIX, it doesn't matter: int = long = 32 bit (usually),
>although you have to specify %hd for short int (16 bit).

I can see you have vast experience on many UNIX machines.

Repeat after me:

    long and int are not the same

>Otherwise, if int = 16 bit, long = 32 bit, you have to use
>%ld for long. That is simply logical, not a "bug"!

No, %d for int, %ld for long.  It doesn't matter how many bits are involved,
the whole issue is to do with the _type_ of the arguments.  Use the right
format specifiers for the right types -- forget bits.


Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''

mwizard@eecs.cs.pdx.edu (Craig Nelson) (03/11/91)

ch@dce.ie (Charles Bryant) writes:

>In article <1991Mar6.173733.430@unhd.unh.edu> rg@msel.unh.edu (Roger Gonzalez) writes:
>>main()
>>{
>>    int     i;
>>    long    j;
>>
>>    for (i = 0; i < 1000; i++, j = i*2)
>>        printf("oh crud: %x %10d %x\r", i, j, i);
>>}

>Surely I am not the only person to notice that j is used before being
>set? (On the first pass only). Maybe our newsfeed is just clogged.
>-- 
>Charles Bryant (ch@dce.ie)

No, you're not the only one.  I wonder if he tried this instead, and then
check for his 'bug':

main()
{ int i=0;j=0;

  for (;i<1000;i++,j=i*2)
      printf("oh crud: %x %10d %x\r", i, j, i);

}

Also,  I was always under the impression that long defaulted to an
integer format (a long one).  I wonder why he is trying to format it
to a double format in the printf() statement ?

Craig Nelson (mwizard@eecs.ee.pdx.edu)

rg@msel.unh.edu (Roger Gonzalez) (03/11/91)

My stupid trivial program that started this whole sordid thread, which has
involved countless flames against me and my ancestry:
>>>main()
>>>{
>>>    int     i;
>>>    long    j;
>>>
>>>    for (i = 0; i < 1000; i++, j = i*2)
>>>        printf("oh crud: %x %10d %x\r", i, j, i);
>>>}                              ^
                                  I was wondering why I had to use %ld
                                  instead of %d, since I never had done so 
                                  in the past.  I wondered if it was an
                                  ansi-ism, and if K&R cc's were just
                                  smarter about %d and could deduce size.
                                  
The correct answer as a few people pointed out, is that printf needs to
know how many bytes to slurp off the stack.  I had had the luck to
always have used machines with sizeof(int)==sizeof(long).  Also, I've
always used machines with "correct" :-) byte ordering.  Since I was
using a PC, a machine I generally try to avoid, I forgot about Intel
byte ordering.  (Little-endian? Never actually had cause to use that
term) So, the high bytes of 'j' get read in as the value for the last
'i' printed.  Since I never went above 1000, this was always 0.  On a
big-endian machine with sizeof(int) != sizeof(long), the output should be
(for example)
a         0 20 
on a PC it is
a        20 0
Voila.  I've been enlightened.  

>ch@dce.ie (Charles Bryant) correctly but pointlessly writes:
>
>>Surely I am not the only person to notice that j is used before being
>>set? (On the first pass only). Maybe our newsfeed is just clogged.

True.  However, since this was supposed to be just a minimalist program to
demonstrate concept, and when I was reducing the screen real estate it
took to list the code, I moved a 'j = i * 2' into the 'for' without a 'j = 0'.
My booboo.

In article <1906@pdxgate.UUCP> mwizard@eecs.cs.pdx.edu (Craig Nelson) writes:
>No, you're not the only one.  I wonder if he tried this instead, and then
>check for his 'bug':
>
>main()
>{ int i=0;j=0;
>
>  for (;i<1000;i++,j=i*2)
>      printf("oh crud: %x %10d %x\r", i, j, i);
>
>}
>
>Also,  I was always under the impression that long defaulted to an
>integer format (a long one).  I wonder why he is trying to format it
>to a double format in the printf() statement ?
>
>Craig Nelson (mwizard@eecs.ee.pdx.edu)

Huh?  I think you're not only missing the point, but just plain -wrong- 
to boot.

AT ANY RATE...

Thank you, if you were polite and helpful..
Eat cow dung and die slowly, if you flamed me..

You wouldn't believe the number of postings that said, in effect, "hey
stupid - you should use %ld, not %d!" I knew that.  Reread the posting;
I wrote "it works correctly with %10ld." I asked WHY was this compiler
MAKING me use %ld, when I had gotten away with %d in the past.  There's
a difference. 

What are the morals of this story?
- using the same types of machines all your life can be hazardous to
  your programming style
- if you want wide readership, post about possible bugs in popular programs
- the less people understand the WHY's, the more emphatically they expound
  on their learned-by-rote rules, as if it were a religious chant
- there are just as many assholes on this group as any other group


Cheers,
    Roger
-- 
"The question of whether a computer can think is no more interesting
 than the question of whether a submarine can swim" - Edsgar W. Dijkstra 
rg@[msel|unhd].unh.edu        |  UNH Marine Systems Engineering Laboratory
r_gonzalez@unhh.bitnet        |  Durham, NH  03824-3525