On Tuesday, March 5, 2019 at 12:16:23 PM UTC-5,
blt_4h9...@ai8rhnz2.com wrote:
> On Tue, 5 Mar 2019 08:35:41 -0800 (PST)
>
james...@alumni.caltech.edu wrote:
> >That doesn't help, because it still doesn't have a unique answer, just
> >different answers on different implementations of C++. All you've done
> >by changing it to "output" is to widen the range of possibilities.
>
> So C++ compilers behave differently with the same source code?
You find that surprising? Why do you think the standard defines
"undefined behavior: behavior for which this document imposes no
requirements" (3.27) and "unspecified behavior: behavior, for a well-
formed program construct and correct data, that depends on the
implementation" (3.28).
The first version of your code is ill-formed, so an implementation need
not even compile it, it's only required to issue a diagnostic. If it
chooses to compile it anyway after issuing the diagnostic, and if you
choose to execute the resulting program despite the diagnostic, then the
behavior is undefined. In terms of object code, that means that anything
is permitted, including no object code at all.
You asked about the generated object code - that's unspecified, being
outside the scope of the C++ standard. The C++ standard only defines the
observable behavior of the resulting program. If there's two or more
ways to generate object code which produce the same observable
behavior, all such ways are equally permitted, and different
implementations can and do make different choices. Given the way that
the C++ standard defines observable behavior, there's always infinitely
many differrent ways to produce the same observable behavior, even if
you target only one particular piece of hardware.
If you ignore the fact that the first function is ill formed, neither
function has a function body that produces any observable behavior. In
terms of object code, that means that any object code that has no
observable behavior is permitted. In particular, the generation of no
object code at all is permitted, but if any object code is generated, it
might be different object code on different implementations.
> ... So perhaps you
> think when presented with "i++" they'll actually do a subtract?
They very well, might, if the code has undefined behavior. That could
happen, for instance, if i starts out with the maximum possible value of
a signed integer type. It could also happen if an operator overload is
invoked, depending upon how that overload is defined. It could also
happen if it's ambiguous as to which operator overload should be
invoked. The behavior of the entire prdogram, including the "i++", could
also be undefined due to a defect in some completely unrelated piece of
code.
Also, i++ might actually be required to perform a subtraction. That will
be the case if i has an unsigned integer type and starts out containing
the maximum value representable in that type. The standard defines the
resulting behavior in terms of computing the mathematical result of
adding 1 to that value, and then (in the general case) adding or
subtracting one more than the maximum value that can be represented in
that type, as many times as needed to bring the result into the range
that can be represented. In this particular case, that means exactly one
such subtraction.
> ... Or if I'd
> asked what is the difference between ++ and -- in the output you'd have
> quibbled about the meaning of output then too?
A question about the output object code for "++" and "--", without
specifying a particular implementation of C++, is just as vague as the
same question about any other code construct. Object code is outside the
scope of the C++ standard, and different implementations can produce
vastly different object code, particularly if generating for different
targets. However, it's perfectly feasible to ask a meaningful question
about the difference in behavior of ++ and --, so long as the context is
one where both constructs have behavior that is defined.