Velocity Reviews > Re: Pointer Arithmetic & UB

# Re: Pointer Arithmetic & UB

Lanarcam
Guest
Posts: n/a

 12-20-2012
Le 20/12/2012 19:21, Robert Wessel a écrit :
> On Thu, 20 Dec 2012 11:00:01 -0500, Ken Brody <(E-Mail Removed)>
> wrote:
>
>> On 12/17/2012 7:33 PM, Shao Miller wrote:
>> [...]
>>
>> Condensed version of the discussion so far, in this subthread:
>>
>> =====
>>
>> Given:
>>
>> extern volatile int x;
>> int i = x + x;
>>
>> And citing several C&V from different standards regarding the fact merely
>> accessing a volatile is a "side effect".
>>
>> Does the above invoke UB? (No sequence point between the two "side effects"
>> of accessing "x".)

>
>
> I think it may. Consider a memory mapped I/O device that returns some
> externally supplied status/data value when you read x, and those
> values were sometimes different on consecutive reads. There's no
> constraint on what order the two reads of x occur. In your example,
> it would make no difference, but if you had "i=(3*x)+ x;" instead,
> which read of x occurred first would definitely make a difference. The
> order of accesses is often critical with I/O devices.
>

If I may, the only safe, readable, bug free way of programming
safety devices, for instance for control is:

Process
Write (once)

extern volatile int x; // Memory mapped
extern volatile int y; // Memory mapped
int i; // Local

i = x; // Read
i = f(i); // Process
y = i; // Write

James Kuyper
Guest
Posts: n/a

 12-20-2012
On 12/20/2012 02:32 PM, Robert Wessel wrote:
> On Thu, 20 Dec 2012 13:40:22 -0500, James Kuyper
> <(E-Mail Removed)> wrote:
>
>> On 12/20/2012 01:21 PM, Robert Wessel wrote:
>>> On Thu, 20 Dec 2012 11:00:01 -0500, Ken Brody <(E-Mail Removed)>
>>> wrote:
>>>
>>>> On 12/17/2012 7:33 PM, Shao Miller wrote:
>>>> [...]
>>>>
>>>> Condensed version of the discussion so far, in this subthread:
>>>>
>>>> =====
>>>>
>>>> Given:
>>>>
>>>> extern volatile int x;
>>>> int i = x + x;
>>>>
>>>> And citing several C&V from different standards regarding the fact merely
>>>> accessing a volatile is a "side effect".
>>>>
>>>> Does the above invoke UB? (No sequence point between the two "side effects"
>>>> of accessing "x".)

....
>> stronger. It's not just saying that the value of x can change, but that
>> the two changes to the value of x, without an intervening sequence
>> point, are allowed to interfere with each other in ways that might be
>> fatal for the continued execution of the program. This was definitely
>> intentional in the case of ordinary writes to x; the committee wanted to
>> discourage the writing of such code. It's less clear that it was
>> intended to apply to the change in the value of x that is allowed, for
>> volatile-qualified variables, to occur as a result of reading x.

>
>
> I'm not sure it is. Well, this example might be, but if we had x and
> y referring to two different I/O ports on the same device, accessing
> them in the wrong order could quite certainly have fatal results for
> the continued execution of the program. IIRC, there was a screw up of
> that nature (programming the video controller in the wrong order) that
> caused many monochrome (PC era) monitors to burn out when they got
> driven by an excessively fast signal. Now while I don't think that
> was the result of a C compiler generating the unfortunate order of
> references because order of evaluation is unspecified (in fact I know
> it wasn't), but the concept applies. IOW we are in the *actual* realm
> of "might cause your computer to catch fire".
>
> So perhaps accessing more than one volatile between sequence points is
> actually undefined?

No, the only relevant rule applies to accessing the SAME object twice
without an intervening sequence point. The problem you're talking about
is only covered by the generically implementation-defined aspects of
what 'volatile' means.

glen herrmannsfeldt
Guest
Posts: n/a

 12-20-2012
Robert Wessel <(E-Mail Removed)> wrote:
> On Thu, 20 Dec 2012 13:40:22 -0500, James Kuyper
> <(E-Mail Removed)> wrote:

(snip, someone wrote)
>>> I think it may. Consider a memory mapped I/O device that returns some
>>> externally supplied status/data value when you read x, and those
>>> values were sometimes different on consecutive reads.

(snip)

>>That would be covered by "unspecified result". "undefined behavior" is
>>stronger. It's not just saying that the value of x can change, but that
>>the two changes to the value of x, without an intervening sequence
>>point, are allowed to interfere with each other in ways that might be
>>fatal for the continued execution of the program.

Seems to me that "volatile" automatically adds an implementation
dependence. The implementation should either define that dependence
or leave it unspecified (that is, defining that you can't rely on it).

The standard provides "volatile" but doesn't specifically define
the results of using it.

(snip)

>>intentional in the case of ordinary writes to x; the committee wanted
>>to discourage the writing of such code. It's less clear that it was
>>intended to apply to the change in the value of x that is allowed, for
>>volatile-qualified variables, to occur as a result of reading x.

In the case of:
volatile int x;
i = x + x;

unless the implementation defines the order, the compiler can evaluate
the x in either order. Well, in this case it doesn't matter, but in
cases where it did.

But volatile requires, as I understand it, the compiler to fetch x
twice from memory. Even without x being an I/O port, if it could
be changed otherwise, the program may test whether i is odd.

volatile int x;
while(x ^ ~x) ;

I probably could have just done x==x, but this was more fun.

The program, then, relies on the fact that at some point x will
change between the two evaluations. Volatile requires that x be
fetched twice. The actual change to x is implementation dependent.

> I'm not sure it is. Well, this example might be, but if we had x and
> y referring to two different I/O ports on the same device, accessing
> them in the wrong order could quite certainly have fatal results for
> the continued execution of the program. IIRC, there was a screw up of
> that nature (programming the video controller in the wrong order) that
> caused many monochrome (PC era) monitors to burn out when they got
> driven by an excessively fast signal.

Well, in addition to the fact that x can have side effects, there
might also be an interrupt (task switch) between the two.

> Now while I don't think that
> was the result of a C compiler generating the unfortunate order of
> references because order of evaluation is unspecified (in fact I know
> it wasn't), but the concept applies. IOW we are in the *actual* realm
> of "might cause your computer to catch fire".

> So perhaps accessing more than one volatile between sequence points is
> actually undefined? At least in the case of I/O devices, I'd have to
> say it is. I'm not sure the C standard covers access I/O devices at
> all, although the possible side affects associated with volatiles
> certainly comes close.

As someone else said, there is a difference between undefined
and implementation defined.

-- glen

Ben Bacarisse
Guest
Posts: n/a

 12-20-2012
Tim Rentsch <(E-Mail Removed)> writes:

> Ken Brody <(E-Mail Removed)> writes:
>
>> On 12/17/2012 7:33 PM, Shao Miller wrote:
>> [...]
>>
>> Condensed version of the discussion so far, in this subthread:
>>
>> =====
>>
>> Given:
>>
>> extern volatile int x;
>> int i = x + x;
>>
>> And citing several C&V from different standards regarding the fact
>> merely accessing a volatile is a "side effect".
>>
>> Does the above invoke UB? (No sequence point between the two "side
>> effects" of accessing "x".)

>
> The answer is no. Arbitrary behavior may arise as a result, but
> implementions are obliged to behave as they would if the side
> effects were ordinary, non-interfering side effects. The term
> "undefined behavior" is just a shorthand for saying something
> about what an implementation may do. The actual behavior for
> this example (and indeed for any volatile-qualified access at
> all) is _unconstrained_, but the behavior is not _undefined_ in
> the sense that the Standard uses the term 'undefined behavior'.

I'm having trouble squaring this with the wording of 6.5 p2:

"If a side effect on a scalar object is unsequenced relative to either
a different side effect on the same scalar object or a value
computation using the value of the same scalar object, the behavior is
undefined."

Or maybe I'm having trouble understanding the point you are making.

<snip>
--
Ben.

Phil Carmody
Guest
Posts: n/a

 12-21-2012
Lanarcam <(E-Mail Removed)> writes:
> Le 20/12/2012 19:21, Robert Wessel a écrit :
> > On Thu, 20 Dec 2012 11:00:01 -0500, Ken Brody <(E-Mail Removed)>
> > wrote:
> >
> >> On 12/17/2012 7:33 PM, Shao Miller wrote:
> >> [...]
> >>
> >> Condensed version of the discussion so far, in this subthread:
> >>
> >> =====
> >>
> >> Given:
> >>
> >> extern volatile int x;
> >> int i = x + x;
> >>
> >> And citing several C&V from different standards regarding the fact merely
> >> accessing a volatile is a "side effect".
> >>
> >> Does the above invoke UB? (No sequence point between the two "side effects"
> >> of accessing "x".)

> >
> >
> > I think it may. Consider a memory mapped I/O device that returns some
> > externally supplied status/data value when you read x, and those
> > values were sometimes different on consecutive reads. There's no
> > constraint on what order the two reads of x occur. In your example,
> > it would make no difference, but if you had "i=(3*x)+ x;" instead,
> > which read of x occurred first would definitely make a difference. The
> > order of accesses is often critical with I/O devices.
> >

> If I may, the only safe, readable, bug free way of programming
> safety devices, for instance for control is:
>
> Process
> Write (once)
>
> extern volatile int x; // Memory mapped
> extern volatile int y; // Memory mapped
> int i; // Local
>
> i = x; // Read
> i = f(i); // Process
> y = i; // Write

*Precisely*, how is

extern volatile int x; // Memory mapped
extern volatile int y; // Memory mapped
y = f(x); // Read, Process, Write

less "safe", less "readable", or less "bug free"?

Phil
--
I'm not saying that google groups censors my posts, but there's a strong link
between me saying "google groups sucks" in articles, and them disappearing.

Oh - I guess I might be saying that google groups censors my posts.

Shao Miller
Guest
Posts: n/a

 12-21-2012
On 12/20/2012 11:00, Ken Brody wrote:
>
> Condensed version of the discussion so far, in this subthread:
>
> =====
>
> Given:
>
> extern volatile int x;
> int i = x + x;
>
> And citing several C&V from different standards regarding the fact
> merely accessing a volatile is a "side effect".
>
> Does the above invoke UB? (No sequence point between the two "side
> effects" of accessing "x".)
>
> =====
>
> The Standard also requires (5.1.2.3p2) that all side effects be
> "complete" at the next sequence point.
>
> Given that whatever side effect the access of "x" may have is outside
> the control of the abstract machine, I fail to see how the sequence
> point requirement applies to the side effect of accessing a volatile.
>
> Consider, for example, a memory-mapped I/O system, where reading from a
> given address causes the printer to start printing whatever is in its
> buffer. How can C enforce the "shall be complete" requirement of
> 5.1.2.3p2? How is "i=x;i+=x;" any better than "i=x+x;"?
>

Yes, it invokes undefined behaviour. If a read of 'x' is a side effect,
then two reads of 'x' are two side effects that could conflict if they
occur simultaneously. That is, since an implementation can say that a
read of 'x' increments a foo counter elsewhere, then two simultaneous
reads can result in two simultaneous increments of the foo counter,
which blows up the computer.

- Shao Miller

Ken Brody
Guest
Posts: n/a

 12-21-2012
On 12/20/2012 1:21 PM, Robert Wessel wrote:
> On Thu, 20 Dec 2012 11:00:01 -0500, Ken Brody <(E-Mail Removed)>
> wrote:
>
>> On 12/17/2012 7:33 PM, Shao Miller wrote:
>> [...]
>>
>> Condensed version of the discussion so far, in this subthread:
>>
>> =====
>>
>> Given:
>>
>> extern volatile int x;
>> int i = x + x;
>>
>> And citing several C&V from different standards regarding the fact merely
>> accessing a volatile is a "side effect".
>>
>> Does the above invoke UB? (No sequence point between the two "side effects"
>> of accessing "x".)

>
>
> I think it may. Consider a memory mapped I/O device that returns some
> externally supplied status/data value when you read x, and those
> values were sometimes different on consecutive reads. There's no
> constraint on what order the two reads of x occur. In your example,
> it would make no difference, but if you had "i=(3*x)+ x;" instead,
> which read of x occurred first would definitely make a difference. The
> order of accesses is often critical with I/O devices.

To me, that's not UB. That might be "unspecified" (or, as Tim Rentsch says,
"unconstrained").

Consider, for example:

i = (3*foo()) + foo();

where:

int foo(void)
{
static int i=0;
return i++;
}

Certainly not UB in any sense of the word.

Tim Rentsch
Guest
Posts: n/a

 12-21-2012
Ben Bacarisse <(E-Mail Removed)> writes:

> Tim Rentsch <(E-Mail Removed)> writes:
>
>> Ken Brody <(E-Mail Removed)> writes:
>>
>>> On 12/17/2012 7:33 PM, Shao Miller wrote:
>>> [...]
>>>
>>> Condensed version of the discussion so far, in this subthread:
>>>
>>> =====
>>>
>>> Given:
>>>
>>> extern volatile int x;
>>> int i = x + x;
>>>
>>> And citing several C&V from different standards regarding the fact
>>> merely accessing a volatile is a "side effect".
>>>
>>> Does the above invoke UB? (No sequence point between the two "side
>>> effects" of accessing "x".)

>>
>> The answer is no. Arbitrary behavior may arise as a result, but
>> implementions are obliged to behave as they would if the side
>> effects were ordinary, non-interfering side effects. The term
>> "undefined behavior" is just a shorthand for saying something
>> about what an implementation may do. The actual behavior for
>> this example (and indeed for any volatile-qualified access at
>> all) is _unconstrained_, but the behavior is not _undefined_ in
>> the sense that the Standard uses the term 'undefined behavior'.

>
> I'm having trouble squaring this with the wording of 6.5 p2:
>
> "If a side effect on a scalar object is unsequenced relative to either
> a different side effect on the same scalar object or a value
> computation using the value of the same scalar object, the behavior is
> undefined."
>
> Or maybe I'm having trouble understanding the point you are making.

The difference is subtle, so let me take another run at explaining
it.

Suppose C had a provision for "magic functions". A magic function
is declared and defined just the same way that ordinary C functions
are (perhaps with an additional 'magic' keyword), and are called
the same way as ordinary functions. However, outside of the
language, including both the Standard itself and also any aspects
known to any implementation, there is a way of setting magic
functions so that they activate a logic control wire whose purpose
(and consequences) are unknown as far as the Standard is concerned
(again including both portable behavior and implementation-defined
behavior). This activation takes place whenever a magic function
is called. Even though the Standard doesn't know what will happen,
it wants to guarantee that the associated logic control wires are
activated, so it stipulates that calling a magic function is always
required, even if, eg, the function body is empty, and if that is
known at every point of call.

Under these hypothetical conditions, calling a magic function has,
at least potentially, the same consequences as undefined behavior
does. However, the act of calling a magic function does not give
an implementation any license to ignore or violate requirements.
This is true because, even though calling a magic function might
do something horrible, _it also might not_, and implementations
must proceed just as they would if nothing bad has happened,
because as far as they know that could be true.

It's important to remember what 'undefined behavior' means, which
is a statement about how implementations may behave. Calling a
magic function has unlimited consequences in how an /execution/ may
behave, but that doesn't eliminate any requirements for how the
/implementation/ must behave. Statements in the Standard are
really about what implementations (ie, mostly compilers) do, not
about what happens during execution. Even though calling a magic
function has potentially unlimited consequences during execution,
it doesn't change what an implementation is obliged to do to
conform to the Standard's requirements. That is the key point.

To get back to volatile, the consequences of accessing a volatile
are just the same as calling a hypothetical magic function. It is
true that performing a volatile-qualifed access counts as a side
effect, but not necessarily a side effect on the object being
accessed. The consequences of accessing a volatile object are
potentially horrible, and as a result something really bad might
happen, but here again _it also might not_. Because it is unknown,
and indeed unknowable, by fiat in the Standard, what the
consequences of a volatile-qualified access will be, implementations
must behave just as they would if the accesses in question did
nothing more than what an ordinary access would do. Ergo the
term 'undefined behavior' does not apply.

Finally, about 6.5 p2. What's being referred to here are side
effects on scalar objects that occur because of language-defined
program actions. Accessing a volatile object is a side effect,
but it is not, for the purpose of 6.5 p2, a side effect on any
particular scalar object. Otherwise, the mere _declaration_ of
a volatile object would potentially provoke undefined behavior,
since such objects may be modified at any time, and nothing in
the Standard defines their sequencing. Also it may be good to
remember that the notion of sequencing is defined only for
evaluations done as part of defined C semantics (per 5.1.2.3 p3).
Any consequences of volatile-access-induced side effects fall
outside the domain of the sequencing rules, because those rules
pertain only to evaluations of program expressions (and then
only those in a single thread). Doing two read accesses of
a single volatile-qualified object might produce horrible
consequences (then again, so might only a single read access),
but even so there is no 'undefined behavior', in the sense
that the Standard uses the term, ie, about what is further
required of the implementation: the execution may go completely
askew, but that doesn't let, eg, the compiler off the hook for

I hope this explanation helped because I am going to stop now.

Tim Rentsch
Guest
Posts: n/a

 12-21-2012
Shao Miller <(E-Mail Removed)> writes:

> On 12/20/2012 11:00, Ken Brody wrote:
>>
>> Condensed version of the discussion so far, in this subthread:
>>
>> =====
>>
>> Given:
>>
>> extern volatile int x;
>> int i = x + x;
>>
>> And citing several C&V from different standards regarding the fact
>> merely accessing a volatile is a "side effect".
>>
>> Does the above invoke UB? (No sequence point between the two "side
>> effects" of accessing "x".)
>>
>> =====
>>
>> The Standard also requires (5.1.2.3p2) that all side effects be
>> "complete" at the next sequence point.
>>
>> Given that whatever side effect the access of "x" may have is outside
>> the control of the abstract machine, I fail to see how the sequence
>> point requirement applies to the side effect of accessing a volatile.
>>
>> Consider, for example, a memory-mapped I/O system, where reading from a
>> given address causes the printer to start printing whatever is in its
>> buffer. How can C enforce the "shall be complete" requirement of
>> 5.1.2.3p2? How is "i=x;i+=x;" any better than "i=x+x;"?
>>

>
> Yes, it invokes undefined behaviour. If a read of 'x' is a side
> effect, then two reads of 'x' are two side effects that could conflict
> if they occur simultaneously. That is, since an implementation can
> say that a read of 'x' increments a foo counter elsewhere, then two
> simultaneous reads can result in two simultaneous increments of the
> foo counter, which blows up the computer.

IMO this conclusion is wrong. The consequences of volatile access (ie,
the extra-linguistic side effects) are outside the domain of 6.5p2,
because it is concerned only with program expressions, not other
unknown memory changes. This view is explained in more detail in my
response to Ben Bacarisse in this thread.

glen herrmannsfeldt
Guest
Posts: n/a

 12-21-2012
Tim Rentsch <(E-Mail Removed)> wrote:
> Ben Bacarisse <(E-Mail Removed)> writes:
>> Tim Rentsch <(E-Mail Removed)> writes:

(snip)
>>> The answer is no. Arbitrary behavior may arise as a result, but
>>> implementions are obliged to behave as they would if the side
>>> effects were ordinary, non-interfering side effects. The term
>>> "undefined behavior" is just a shorthand for saying something
>>> about what an implementation may do. The actual behavior for
>>> this example (and indeed for any volatile-qualified access at
>>> all) is _unconstrained_, but the behavior is not _undefined_ in
>>> the sense that the Standard uses the term 'undefined behavior'.

>> I'm having trouble squaring this with the wording of 6.5 p2:

>> "If a side effect on a scalar object is unsequenced relative to either
>> a different side effect on the same scalar object or a value
>> computation using the value of the same scalar object, the behavior is
>> undefined."

>> Or maybe I'm having trouble understanding the point you are making.

Before there was "volatile", there was PL/I and the ABNORMAL attribute.

Now, PL/I had multitasking pretty much from the beginning, so there
was always a way that a variable could change at unexpected times.

A compiler wasn't supposed to optimize, for example, A+A as 2*A,
as A might change.

I don't know C11 well at all, has multitasking, or multithreading,
been added now? Is there a way, within a C program (not counting
I/O registers and such) for a variable to change within a statement,
other than as side effects of that statement?

If so, then the compiler has to allow for that.

Otherwise, it seems to me, that "volatile" has to be implementation
defined. As a door that an implementation can use in implementaion
specific ways. If an implementation allows for variables to be I/O
registers, then the compiler has to compile as appropriate for
that case.

> The difference is subtle, so let me take another run at explaining
> it.

> Suppose C had a provision for "magic functions". A magic function
> is declared and defined just the same way that ordinary C functions
> are (perhaps with an additional 'magic' keyword), and are called
> the same way as ordinary functions. However, outside of the
> language, including both the Standard itself and also any aspects
> known to any implementation, there is a way of setting magic
> functions so that they activate a logic control wire whose purpose
> (and consequences) are unknown as far as the Standard is concerned
> (again including both portable behavior and implementation-defined
> behavior).

Stretching this farther than I probably should, consider a function
in the same file as its call, and that the function doesn't do
anything, as the compiler can plainly see. Now, consider that
one might use a linkage editor (the OS/360 linker can do this)
to later replace that function with a different one.

> This activation takes place whenever a magic function
> is called. Even though the Standard doesn't know what will happen,
> it wants to guarantee that the associated logic control wires are
> activated, so it stipulates that calling a magic function is always
> required, even if, eg, the function body is empty, and if that is
> known at every point of call.

There is much discussion on comp.lang.fortran on what compilers
might do when optimizing function calls. Seems like in Fortran,
a compiler is allowed to optimize out the call with very little
reason, consider:

x=0*fclose(out);

> Under these hypothetical conditions, calling a magic function has,
> at least potentially, the same consequences as undefined behavior
> does. However, the act of calling a magic function does not give
> an implementation any license to ignore or violate requirements.
> This is true because, even though calling a magic function might
> do something horrible, _it also might not_, and implementations
> must proceed just as they would if nothing bad has happened,
> because as far as they know that could be true.

OK, but there is no "magic" keyword to apply to functions.
So, should compilers always call functions?

> It's important to remember what 'undefined behavior' means, which
> is a statement about how implementations may behave. Calling a
> magic function has unlimited consequences in how an /execution/ may
> behave, but that doesn't eliminate any requirements for how the
> /implementation/ must behave. Statements in the Standard are
> really about what implementations (ie, mostly compilers) do, not
> about what happens during execution. Even though calling a magic
> function has potentially unlimited consequences during execution,
> it doesn't change what an implementation is obliged to do to
> conform to the Standard's requirements. That is the key point.

OK, but magic functions aren't defined (last I knew) in the
standard. The "volatile" attribute is, but, as I understand,
not well enough to say what it actually does.

> To get back to volatile, the consequences of accessing a volatile
> are just the same as calling a hypothetical magic function. It is
> true that performing a volatile-qualifed access counts as a side
> effect, but not necessarily a side effect on the object being
> accessed. The consequences of accessing a volatile object are
> potentially horrible, and as a result something really bad might
> happen, but here again _it also might not_. Because it is unknown,
> and indeed unknowable, by fiat in the Standard, what the
> consequences of a volatile-qualified access will be, implementations
> must behave just as they would if the accesses in question did
> nothing more than what an ordinary access would do. Ergo the
> term 'undefined behavior' does not apply.

OK, but it seems to me that the standard, separate from implementations,
should only cover what standard conforming programs can do.

An implementation may allow variables to be I/O ports, and use the
"volatile" keywork, but the standard does not have any such wording.

> Finally, about 6.5 p2. What's being referred to here are side
> effects on scalar objects that occur because of language-defined
> program actions. Accessing a volatile object is a side effect,
> but it is not, for the purpose of 6.5 p2, a side effect on any
> particular scalar object. Otherwise, the mere _declaration_ of
> a volatile object would potentially provoke undefined behavior,
> since such objects may be modified at any time, and nothing in
> the Standard defines their sequencing.

Yes. My feeling is that the keyword is there to allow for
implementation defined behavior. But implementation defined,
is distinct from undefined.

> Also it may be good to
> remember that the notion of sequencing is defined only for
> evaluations done as part of defined C semantics (per 5.1.2.3 p3).
> Any consequences of volatile-access-induced side effects fall
> outside the domain of the sequencing rules, because those rules
> pertain only to evaluations of program expressions (and then
> only those in a single thread). Doing two read accesses of
> a single volatile-qualified object might produce horrible
> consequences (then again, so might only a single read access),
> but even so there is no 'undefined behavior', in the sense
> that the Standard uses the term, ie, about what is further
> required of the implementation: the execution may go completely
> askew, but that doesn't let, eg, the compiler off the hook for
> generating bad code.

It does seem that the compiler should follow the code as written.
If there is one reference to a variable, it should be referenced once,
for the implementation dependent definition of reference.

volatile int x;
y=2*x;
z=x+x;

In this case, y should always be even, z has the possibility
of not being even, and the compiler should allow for that.

> I hope this explanation helped because I am going to stop now.

-- glen