Re: GCC not doing the correct thing?
Re: GCC not doing the correct thing?
- Subject: Re: GCC not doing the correct thing?
- From: Thomas Castiglione <email@hidden>
- Date: Mon, 11 Nov 2002 20:21:50 +0800
I couldn't agree more. The GOOD news is that that code works perfectly
in GCC, for me at least. Simple test case, using your example:
#define CUBE(A) ((A) * (A) * (A))
main() {
char *a = "ABCD";
printf("%s\n", a);
cube(*a++);
printf("%s\n", a);
}
That compiles fine with no options in GCC 3.1, and prints out
ABCD
D
as you would expect.
On Sunday, November 10, 2002, at 05:35 AM, Domain Administrators wrote:
Forgive me for my impertinence, but if the example code were to be
"undefined" by definition, we would all be in a lot of trouble. But
this is not so, and the example given makes the argument all the
easier.
Let's review. We have a macro which I will retype as
#define CUBE(A) ((A) * (A) * (A))
And we have a sample parameter given as
*ptr++
Which supposedly renders the expression undefined.
First, let's substitute as the macro preprocessor has to.
((*ptr++) * (*ptr++) * (*ptr++))
This is so patently simple I am surprised - and shocked - others
don't get it. C uses both binding, precedence, and associativity to
define how expressions are broken down and parsed. For example, we
have both prefix and postfix increment and decrement operators, and
we know what the difference is there. In the expression
*ptr++
We know that ptr is dereferenced before it is incremented, because
of the left to right associativity. We also know that * and ++ are
bound before the multiplication operator. What we get is the
following. Let us say that ptr points to an array in memory such as
the following.
A B C D E F G H I J K L M N
It doesn't really matter how the parser evaluates the expression, as
the substituted parameter is always the same. When the first
expression *ptr++ is evaluated, the parser gets "A" and then
increments the pointer to the next address in the array.
When the next expression is evaluated, the pointer is again
dereferenced, giving "B" before incrementing the pointer again. And
so forth.
The end result - no matter what associativity is used - is A * B *
C, with ptr thereafter pointing to the cell with "D" in it.
As stated, C uses both binding, precedence, and associativity. The
rules for binding tell us that * and ++ on ptr get evaluated before
this operand is considered with its operator *. The rules of
associativity tell us that the entire expression will be evaluated
left to right. The rules of precedence are not relevant here, as the
same operator is used throughout.
Dennis Ritchie's original compiler for C, before Steve Johnson's
pccm, was recursive in design, and it is easy to see why he chose
this model. Every expression must be broken down into
sub-expressions, etc., and each of these sub-expressions must be
evaluated first - or according to the above-stated rules.
This is all in the original K/R. We used to have these tables pasted
to our walls - they're that important to know. The thought that
programmers of today not be aware of these very basic rules for
parsing, and think that expressions of the relatively easy CUBE
example given should be "undefined" scares me. The prospect that GCC
or some other compiler get hiccups with something like this shocks
me.
--- "Clark S. Cox III" <email@hidden> wrote: > -----BEGIN PGP
SIGNED MESSAGE-----
Hash: SHA1
On Friday, Nov 8, 2002, at 15:51 US/Eastern, Domain Administrators
wrote:
Absolutely nothing. You're right. Even the order of the accesses
of
x in x*x*x is defined in the associativity of the language. It
has
to be.
If GCC has problems with this, then we're in trouble. R.
What's undefined about the following?
cube( (*ptr++) )
Neither the order of memory fetches or the order of stores is
defined.
Operator precedence and associativity are irrelevant here. for
example,
in the following expression (x+y*z), the compiler is allowed to:
fetch all three variables at once, before performing any
operations
fetch each individual variable as the need arises
fetch them in a random order, as long as they are loaded before
the
actual calculation is performed
In the following example (which is a perfectly legal statement):
a = x++ + y++ + z++;
The compiler is only required to:
1) fetch the values of the three variables
2) add them together
3) assign the result to a
4) increment each of the three variables
As long as the incrementing happens after the fetching, the
compiler is
well within it's right to do whatever it pleases (in fact, for
whatever
reason, step 4 could come between 1 and 2, or between 2 and 3)
However in this example (which is invokes undefined behavior):
a = x++ + x++ x++;
Since the C standard does not specify when the increment takes
place
(i.e. it only has to take place sometime after the initial value
is
fetched, but before the next sequence point), the compiler would
be
well within it's right to compile this as:
a = x+x+x;
x += 3;
or
a = (x+1)+(x+1)+(x+1)
x += 3;
or
a = x;
a += x++;
a += x++;
a += x++;
Each of which yield different results. So the result of such an
expression is "undefined" as per the standard, and in fact it is
explicitly stated to be so in the standard.
- --
http://homepage.mac.com/clarkcox3/
email@hidden
Clark S. Cox, III
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (Darwin)
iEYEARECAAYFAj3MJ58ACgkQd6STocYT1xUF+QCgl5k7j4K3fh+ReOI8tY6l2r7n
TZsAnimyRSmzvraP7UeHbCUeZerZFQV1
=yh1e
-----END PGP SIGNATURE-----
Everything you'll ever need on one web page
from News and Sport to Email and Music Charts
http://uk.my.yahoo.com
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.