Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!bloom-beacon!think!ames!sdcsvax!ucbvax!decvax!decwrl!labrea!rocky!rokicki From: rokicki@rocky.STANFORD.EDU (Tomas Rokicki) Newsgroups: comp.lang.c,comp.sys.atari.st,comp.sys.amiga Subject: Re: 32bit = 16bit x 16bit Message-ID: <663@rocky.STANFORD.EDU> Date: Mon, 12-Oct-87 16:36:44 EDT Article-I.D.: rocky.663 Posted: Mon Oct 12 16:36:44 1987 Date-Received: Wed, 14-Oct-87 02:11:31 EDT References: <141@kesmai.COM> Reply-To: rokicki@rocky.UUCP (Tomas Rokicki) Organization: Stanford University Computer Science Department Lines: 68 Xref: mnetor comp.lang.c:4853 comp.sys.atari.st:5645 comp.sys.amiga:9319 > the phrase on pg184 in K&R which says that an expression with two ints > should produce an int (their ints are 16 bits) REQUIRE that they sign > extend or they will fail some of their commercial customers acceptance > suites. Personally I think they are full of it. Actually, no, they are quite correct. If sizeof(int)==2, and int x,y ; and long z; and sizeof(long)==4, then z = x * y should generate muls d1,d0 ext.l d0 according to K&R; the result *must be* of type int (2 bytes) and therefore it must be coerced into a long. The correct way to do this is z = x * (long)y ; which usually generates ext.l d0 ext.l d1 ; both operands must be long jsr .muls but smart compilers (like Manx 3.4) will generate the equivalent muls d1,d0 because the two are exactly idential. (Similarly, idiotic compilers will generate, for char *p, *q ; if (*p==*q) move.b (a0),d0 ext.w d0 move.b (a1),d1 ext.w d1 cmp.w d0,d1 because theoretically, all operations are performed with at least int accuracy, but smart compilers will generate cmp.b (a0),(a1) you would be surprised how many generate the former! Try it.) > Does anyone know of a commercial test suite that checks to make sure that > y = x * x where x is a 16 bit int and y is long (32 bits) produces garbage > instead of the proper result? Seems like just the kind of thing I would > want in my software. Why have good numbers when I could have garbage? The rules for C type coercion are well laid down and fairly unambiguous. Violating them so this one case works is not a good idea. Specifically, int x, y; long z ; z = x * y ; /* is not exactly equivalent to */ z = (long)x * (long)y ; /* but */ z = x * (long)y ; /* is equivalent to */ z = (long)x * (long)y ; and the lone muls will do the latter, but not the former, if the compiler is smart enough. And it doesn't take a much smarter compiler to handle x * (long)y correctly. -tom