Subject: Re: off_t and int/long
To: None <arnej@pvv.unit.no, hiroy@netcom.com, port-i386@NetBSD.ORG>
From: Bruce Evans <bde@zeta.org.au>
List: port-i386
Date: 05/19/1996 13:39:35
>(Example program with "strange" output:)

> > % cat xxx.c
> > /* */
> > #include <stdio.h>
> > 
> > long	b = 1 << 24;
> > u_long	c = 1 << 9;
> > int	d;
> > 
> > void
> > f(off_t a)
> > {
> > 	printf("a=0x%016qx\n", a);
> > }
> > 
> > int
> > main()
> > {
> > 	for(d = 1; d >= -1; d -= 2) {
> > 		f(b * c + d);
> > 		f((off_t)(b * c + d));
> > 		f((off_t)b * c + d);
> > 		f(b * (off_t)c + d);
> > 		f(b * c + (off_t)d);
> > 	}
> > 	return (0);
> > }
> > % cc xxx.c
> > % ./a.out
> > a=0x0000000000000001
> > a=0x0000000000000001
> > a=0x0000000200000001
> > a=0x0000000200000001
> > a=0x0000000000000001
> > a=0x00000000ffffffff
> > a=0x00000000ffffffff
> > a=0x00000001ffffffff
> > a=0x00000001ffffffff
> > a=0xffffffffffffffff

>Yes.  Welcome to the wonderful world of Ansi C integral promotions.
>This is entirely correct and the expected result.

>Not exactly *intuitive*, mind you, but nevertheless right.

Actually, welcome to the not so wonderful world of undefined behaviour.
b * c overflows so the result may be anything.  It may even be "correct".
(ANSI C's integral promotions are intuitive in this case.  The unintuitive
cases involve loss of unsignedness.  E.g.,

	(((unsigned char)0xff) << 24) >> 24

gives an implementation-defined value, 0xffffffff on many 32-bit machines.)

>Any Ansi
>C compiler should give the same results, and I just tried Sun, SGI,
>and DEC with the same results.

Anyway, any ANSI compiler should fail to compile this program, because
u_long and off_t aren't ANSI.  If they are defined, perhaps by including
<sys/types.h>, then "0x%016qx" causes undefined behaviour.  It may even
be "correct".

Bruce