James Kanze
11/14/2008 9:52:00 AM
On Nov 13, 11:26 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> James Kanze wrote:
> >> What do you expect should happen? The standard only says
> >> that the variable is incremented before usage.
> > No it doesn't. As Pete has already said, it's irrelevant
> > here, since the code has undefined behavior, but all the
> > standard says is that the variable will be incremented
> > before the next sequence point. Even if there wasn't
> > undefined behavior.
> But (as far as I know) jumping to a function call (in this
> case printf) marks a sequence point, so the variable must have
> been incremented before the code jumps to the printf function.
Yes. Calling a function or returning from one are sequence
points.
> I think it's thus pretty unambiguous that the variable a will
> have been incremented twice before the printf call is
> executed, and thus will have a value of 7.
Not in this case, because the standard says that there is
undefined behavior.
> It's also pretty unambiguous that the value 5 cannot be part
> of the multiplication because the very definition of the
> prefix++ operator makes that impossible.
Not in this case, because the standard says that there is
undefined behavior. Also because there is no sequence point
between the incrementation and the multiplication, so the update
to the variable need not have taken place. But the undefined
behavior trumps.
> The only thing which in practice is not guaranteed in
> "++a*++a" is in which order the variable a is incremented and
> its value used in with the binary operator*.
Nothing is guaranteed in practice, because there is undefined
behavior. Just what part of undefined don't you understand?
> Thus, in practice, only four things can conceivably happen:
> 1) The first "++a" is executed first, incrementing the value of a, and
> the value of that expression will be 6. After this the second "++a" is
> executed and this results in 7 as the second operand, and thus the
> result will be 42.
> 2) The reverse happens: The second "++a" is executed first, its value
> taken, and then the first one. The result of the multiplication will
> still be the same.
> 3) Both "++a" operators are executed first, after which the value of a
> (ie. 7) is used as the parameters of the multiplication, which results
> 4) The compiler decides that the value of the expression "++a" is 6, and
> thus uses 6 as the value for both operands of the operator*. Thus the
> result of the multiplication will be 36. (Although I would say that this
> case is the most unlikely of the four in practice.)
That's the only one I've actually seen (but I've not looked
much). In C, with the Microsoft compiler.
Not actually seen by me, but I have heard it reported that on
certain machines, such expressions result in reading and writing
from the same address at the same time (on a machine with dual
port memory), which results in the memory freezing up, and the
operations never finishing. (It sounds a bit strange from what
I know of hardware, but such machines have purportedly existed.)
All of which really isn't relevant, because the expression
contains undefined behavior. Since the C90 standard, at least.
(At least two people, including myself, have argued that this
should be fixed. But there's been absolutely no support for it
in the committee.)
> I see no logical reason why any compiler would produce
> anything else than something that prints 36, 42 or 49.
What part of undefined don't you understand? There's no
requirement that undefined behavior be logical.
> But of course this is just theoretizing about compiler
> behavior in practice. It's not like you should ever use
> anything like "++a*++a".
Agreed. In practice, even if it were only unspecified, what's
the use of an expression which produces random results.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34