Re: (i++ * i++)
thp_at_cs.ucr.edu
Date: 04/18/04
- Next message: Paul Mensonides: "Re: Index a #define string"
- Previous message: Ioannis Vranos: "Re: Would a static_cast be better style here?"
- In reply to: Dave Moore: "Re: (i++ * i++)"
- Next in thread: thp_at_cs.ucr.edu: "Re: (i++ * i++)"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sun, 18 Apr 2004 20:38:36 +0000 (UTC)
Dave Moore <dtmoore@rijnh.nl> wrote:
: thp@cs.ucr.edu wrote in message news:<c5pnt7$1pc$1@glue.ucr.edu>...
:> Rolf Magnus <ramagnus@t-online.de> wrote:
:> [...]
:> : I'm not sure, but it looks to me as if "thp@cs.ucr.edu" wanted to
:> : enforce a crash if the two references refer to the same integer, but
:> : got it all wrong in several ways. First, *(int*)0 won't necessarily
:> : crash.
:>
:> Not a crash. It's merely an alternative way to permit undefined
:> behavior when i1 and i2 are the same object, the need to appeal to C89
:> 6.3 etc.
:>
:> : Instead it will have undefined behaviour, and actually, I'd
:> : expect it to be optimized away on most compilers because the value
:> : isn't used, so it would just be a no-op.
:>
:> Right. It should generate no overhead but simply allow conforming
:> implementations to assume that i1 and i2 are distinct objects.
:>
:
: Ok .. but here is the part I don't understand ... what is supposed to
: happen when the above condition is violated? In the example when
: f(i,i) is called, what is supposed to happen as you see it? As I said
: in an earlier post ... I tried it on GCC 3.3 and there was no crash.
What you obtained was "undefined behavior", which can be anything at
all and need not appear cause an identifiable crash. In general,
wrong answers are much more damaging that a full-on crash. (That's
why I recommend and use the assert macro so much.)
: This seems to me to be highly undesirable behavior ... your code is
: supposed to "allow the comiler to assume i1 and i2 are distinct
: objects", but I think then you must enforce a crash in the case that
: they are not ... or are you still leaving that up to the programmer?
Clause 5.4 on page 63 of the C++ current Standard states:
Between the previous and the next sequence point a scalar object
shall have its stored value modified at most once by the evaluation
of an expression. Furthermore, the prior value shall be accessed
only to determine the value to be stored.
Otherwise the behavior resulting from that evaluation is "undefined",
which (as I said before) simply means that *anything* goes, i.e., the
program has broken its contract with the conforming implementation.
In the case at hand, this gives the optimizer permission to assume
that &i1 and &i2 are distinct objects (since otherwise the behavior is
undefined) without incurring the overhead of actually computing and
comparing their addresses.
I'm merely pointing out that evaluating the expression
"&i1!=&i2||*(int*)0" confers the same permission, again without
overhead. But this time the permission is explicit and shouldn't come
as a surprise to the programmer.
:> : Further, it's not only
:> : It should be replaced by something like:
:> :
:> : assert(&i1 != &i2);
:>
:> I'd prefer
:>
:> #define assume(exp) ((exp)||*(int*)0)
:>
:> since assert's argument must be evaluated, when NDEBUG is undefined,
:> and isn't seen by the compiler, when NDEBUG is defined.
:>
:
: Again, there is no point to this as far as I can tell, since it is not
: guaranteed to force a crash. As you already agreed, a compiler will
: likely optimize away the *(int *)0 statement, since the result is
: never used. So then there is no crash, which was the whole point of
: the assert statement above. Maybe we are arguing apples and oranges
: here?
A crash is (almost) always preferrably to a wrong answer, so I agree
that "assert(&i!=&j)" is vastly preferrable to "assume(&i!=&j)" in
almost every case. Unfortunately, the assert statement carries an
overhead -- in the case at hand:
- When NDEBUG is undefined, "&i!=&j" must be evaluated.
- When NDEBUG is defined, "&i!=&j" cannot be assumed.
IMHO, the real importance of the assume() macro is that it removes any
reasonable excuse for retaining the quoted portion of 5.4, which I
consider to be a very dangerous pitfall.
Tom Payne
- Next message: Paul Mensonides: "Re: Index a #define string"
- Previous message: Ioannis Vranos: "Re: Would a static_cast be better style here?"
- In reply to: Dave Moore: "Re: (i++ * i++)"
- Next in thread: thp_at_cs.ucr.edu: "Re: (i++ * i++)"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|