Akinori MUSHA wrote: > I observed gcc 2.95.4 and gcc 3.1 interpret (or maybe optimize) the > following code differently (CFLAGS=-O): > > int main(void) > { > unsigned char i = 127; > printf("%d\n", ((char)(i << 1)) / 2); > return 0; > } >
Cool... > gcc 2.95.4 says it's -1, Promotion of operand to int; conversion to lvalue type after the operation. > whereas gcc 3.1 says it's 127. Promotion of operand to lvalue type. > On FreeBSD > char should be signed, so I suspect it's a (optimization) bug of gcc > 3.1 which should be fixed. Or we'll have to do a mass audit of the > whole src tree to check and fix the similar expressions. Technically, I think, because of the parenthesis, that GCC 2.95 is right, and GCC 3.1 is wrong. Given that the conversion to "char" is done prior to the division, it should happen first. >From the assembly, it looks like 3.1 is treating "/2" as ">>1", and illegally canceling out the "<<1" with the ">>1" *before* the conversion. Or maybe it's the conversion to int that happens on the stack value for a %d argument to printf... Maybe one of out C standards people can define when the conversion is defined to occur, so we can get a real ruling. Note that: int main(void) { unsigned char i = 127; printf("%d\n", (char)((i << 1) / 2)); return 0; } ...yields 127 on gcc 2.95, so it's definitely order of conversion being totally screwed by gcc 3.1. Basically, it's assuming commutability where it's not present. > In any case, this behavior makes moused(8) return a stupid value of > 127 when you roll the mouse wheel up under ps/2-sysmouse-intellimouse > protocol. Attached is a patch that makes the whole expression look > more logical and works around the above behavior at the same time. [ ... ] > - act->dz = ((char)(pBuf[5] << 1) + (char)(pBuf[6] << 1))/2; > + act->dz = ((char)(pBuf[5] << 1) + (char)(pBuf[6] << 1)) >> 1; This is *soooooooooo* counter intuitive that it's evil! -- Terry To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-current" in the body of the message