C compiler implements wrong semantics

Neville D. Newman NEVILLE%umass-cs.csnet at csnet-relay.arpa
Sun Feb 2 20:11:49 AEST 1986


This is posted to unix-wizards instead of to net.lang because i believe
that it shows faulty semantics in the Unix C compiler.  i don't know
the proper to get to arbitrary newsgroups, being an Internet person, so
if the moderator would kindly forward it there i would appreciate it.

While digging through the guts of the portable C compiler, i noticed
that it produced exactly the same code for two statements that i think
have different semantics.  According to my C references, the unary
operators have precedence over binary operators (and are evaluated right
to left).  The rule for pre- and post-increment (and -decrement) operators
is, of course, that a++ changes the value of  a  after the value of the
term is used, so that the change is a side-effect.  ++a, on the other
hand changes the value of  a  before the term is used and is therefore
entirely equivalent to  (a += 1) or (a = a+1).

The C compiler on our 4.2bsd system, however, seems to consider the "before"
and "after" to be relative to the higher level *expression* being evaluated
rather than just the individual term.  In the assembly output for the simple
program that follows, the increment or decrement is always placed before or
after the block of statements that implement the C assignment, never in the
midst of that block where it should sometimes appear.

According to my books, if a is 5, then (a++ + a) ought to evaluate to 11.
On 4.2bsd (or any system using the pcc, i imagine) it evaluates to 10.
On VMS with VAX-C v2.1, it evaluates to 11.
On CP/M-68K with the Alcyon compiler, it is 10.  The Alcyon compiler strives
for compatibility with version 7 Unix.

So the questions for the day are:  Is pcc "right" because it is sort of the
defacto standard?  (i have a friend who claims that BNF and such are useless,
the compiler is the only definition of a language that counts)  Is this
discrepancy between Unix C's behaviour and description already widely known
and carefully worked around?  Should i attempt to fix it and possibly break
some code or leave it alone for old time's sake?

This code should check several facets of the pre-/post- increment/decrement
problem.  The pre-increments should be give results of 12 on all systems,
or else there's a *bad* problem.  The post-increments give 10 on Unix, 11
on VMS.  i think 11 is correct, based on the language description.


#include <stdio.h>

main() {
int a;
int b;

/* check post-increments */
a = 5;
b = a + a++;
printf("b = a + a++   yields  %d\n",b);
a = 5;
b = a++ + a;
printf("b = a++ + a   yields  %d\n",b);
a = 5;
b = a + (a++);
printf("b = a + (a++) yields  %d\n",b);
a = 5;
b = (a++) + a;
printf("b = (a++) + a yields  %d\n",b);

/* check pre-increments */
a = 5;
b = a + ++a;
printf("b = a + ++a   yields  %d\n",b);
a = 5;
b = ++a + a;
printf("b = ++a + a   yields  %d\n",b);
a = 5;
b = a + (++a);
printf("b = a + (++a) yields  %d\n",b);
a = 5;
b = (++a) + a;
printf("b = (++a) + a yields  %d\n",b);

}



More information about the Comp.unix.wizards mailing list