cast changes meaning of auto-increment?
Chris Torek
chris at mimsy.UUCP
Wed Sep 14 05:33:24 AEST 1988
In article <901 at mina.liu.se> mikpe at mina.liu.se (Mikael Pettersson) writes:
>Consider the following piece of code:
>--begin-example--
>{
> int i = 27;
> register char *cp, *oldcp;
>
> oldcp = cp = (char *)&i;
> printf("i == %d, ", *(int *)cp++); /* should print `27' */
> printf("and cp increased by %d\n", cp-oldcp); /* 4 or 1 ? */
>}
>--end-of-example--
>My question is: what should be printed by the second printf, 4 or 1?
The answer is 1; but:
>Many PCC-based m68k compilers (including SUN's) print `4' but I know of at
>least two (GCC on our SUNs and GOULD's UTX/32 compiler) that insist on
>printing `1'.
Any compiler that does this is buggy. It is not even a question of
whether one can increment the result of a cast (many PCC compilers
allow this).
>Since a cast doesn't produce an lvalue, I assume the ++ should be applied
>to `cp' after the int was fetched (i.e., cp should increase by 1) ....
All you need do to answer this particular question is to look at the
operator precedence. `++' operates before `cast'. The expression
`i = *(int *)cp++' must thus be evaluated in the (virtual) order:
cp (lvalue, type `char *', value &i)
postfix-++ (rvalue, type `char *', value &i)
[side effect: last lvalue (cp) += sizeof(char)]
(int *) (rvalue, type `int *', value &i)
* (lvalue, type `int', value i)
The only way the bug would make any sense at all (other than as a
clear bug) would be if the expression were written
i = *((int *)cp)++);
to force the order to
cp (lvalue, type `char *', value &i)
(int *) (rvalue, type `int *', value &i)
postfix-++ (error, rvalue, type `int *', value &i)
[side effect: last lvalue (none) += sizeof(int)]
* (rvalue, type `int', value i)
which is (as Mike notes above) illegal, but if the compiler forgets
to change `l' to `r' value after the cast would produce what Sun's PCC
does.
Note that the SunOS compilers that get
*(int *)cp++
wrong get
*(int *)++cp
right. Also, if we run the compiler with debugging on, we can
even see that the problem is in the code generator, which is simply
overly liberal with its reg at + addressing modes:
f(){
register char *cp;
register int *ip, i;
i = *(int *)cp++;
i = *(int *)ip++;
}
(/lib/ccom -Xe)
0x509d0) =, int, 17, 4
0x50850) REG, 0x0, 7, int, 17, 4
0x509b0) U*, int, 17, 4
0x50910) ++, PTR int, 17, 4
0x508d0) REG, 0x0, 13, PTR char, 17, 2
0x508f0) ICON, 0x1, 16384, int, 0, 4
movl a5 at +,d7
Note that a5 was supposed to be incremented by 1 (the value
of the ICON at 0x508f0), not 4.
0x50b50) =, int, 17, 4
0x509f0) REG, 0x0, 7, int, 17, 4
0x50b30) U*, int, 17, 4
0x50ab0) ++, PTR int, 17, 4
0x50a70) REG, 0x0, 12, PTR int, 17, 4
0x50a90) ICON, 0x4, 16384, int, 0, 4
movl a4 at +,d7
This time, a4 was supposed to be incremented by 4 (and was).
(If I had compiler sources, I could probably even provide a fix,
but Sun will not sell those.)
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: chris at mimsy.umd.edu Path: uunet!mimsy!chris
More information about the Comp.lang.c
mailing list