2 doubts !

int i =10;
int a = i++ + i++;
and also, i tried this in gcc, answer was 20, so what the sequence points
for evaluation of something like i++ + i++ ???

2.a = i++; is not defined in the language........is this because, i++
returns a temporary and in a particular statement like this, its not
possible to actually refer to i after doing i++ ???
thanking you,
ranjan.

Advertisements

> hello everybody,
And a howdy right back.
> i have 2 doubts .
If you're down to only two, you have achieved enlightment.
> 1. is this always defined ??
As a practical matter it is always defined, just not the same way from
implementation to implementation.
> int i =10;
> int a = i++ + i++;
> and also, i tried this in gcc, answer was 20, > so what the sequence points
> for evaluation of something like i++ + i++ ???
The semicolon at the end of the statement. There are no sequence
points within the statement.

It is even possible for the answer to be 21.

Please never write actual programs this way. The debugging job might
fall on me or some other busy person. ;-)
> 2.a = i++; is not defined in the language........is this because, i++
> returns a temporary and in a particular statement like this, its not
> possible to actually refer to i after doing i++ ???

Possible? absolutely. Meaningful or recommended? absolutely NOT.
There is no sequence point across '=' either. Therefore the result
could end up at either the original 'i' location or at 'i+1'. It's a
fielder's choice for the compiler. Some may warn you about this
construct, others won't.
> thanking you,
> ranjan.
You're welcome. Safe journey and much happy programming.

Advertisements

maadhuu wrote:
> i have 2 doubts .
>
> 1. is this always defined ??
>
> int i =10;
> int a = i++ + i++;
> and also, i tried this in gcc, answer was 20, so what the sequence points
> for evaluation of something like i++ + i++ ???
>
> 2.a = i++; is not defined in the language........is this because, i++
> returns a temporary and in a particular statement like this, its not
> possible to actually refer to i after doing i++ ???

In an expression that contains no sequence points an object may not be
modified and accessed in different subexpressions (since the side
effects of the subexpressions may take place in any order).

Undefined behaviour, i is modified twice without intervening sequence
point. See FAQ section 3.2.
>2.a = i++; is not defined in the language........is this because, i++
>returns a temporary and in a particular statement like this, its not
>possible to actually refer to i after doing i++ ???

Undefined behaviour, i is evaluated and modified without intervening
sequence point. See FAQ section 3.1.

The statement is never defined. It is practically the definition of
"undefined behavior". (Check any C language FAQ.)

There is only one sequence point -- the ";" at the end. There are no
sequence points within the statement itself.

The fact that your particular implementation of gcc happens to set
"a" to 20 is irrelevent, as another compiler, or even the next release
of gcc, might result in 21, or any other value. Also, there is no
guarantee (as I understand it) that "i" will end up being 12.

It is possible that the compiler generates the equivalent of any of the
following:

a = i + i;
i++;
i++;

or

int temp1 = i++;
int temp2 = i++;
a = temp1 + temp2;

or

int temp = i++;
a = temp + i;
i++;

or anything else.
> 2.a = i++; is not defined in the language........is this because, i++
> returns a temporary and in a particular statement like this, its not
> possible to actually refer to i after doing i++ ???

It is because there is no sequence point within the statement, only the
";" at the end is a sequence point.

Therefore, whether "a" refers to the original value of i, or the
incremented value of i, is undefined.

It is possible that a compiler generates code equivalent to:

a = i;
i++;

or

int temp = i++;
a = temp;

While the above two are the most likely scenarios, there is nothing
in the language definition to prevent anything else from occurring
as well. (Google for "nasal demons".)

On 2005-09-14 09:56:43 -0400, "Novitas" <> said:
>> hello everybody,
> And a howdy right back.
>
>> i have 2 doubts .
> If you're down to only two, you have achieved enlightment.
>
>> 1. is this always defined ??
> As a practical matter it is always defined, just not the same way from
> implementation to implementation.

Regardless of whether or not it does anything on a particular platform
does not make it defined (practically or not). It is undefined
behavior, plain and simple.
>
>> int i =10;
>> int a = i++ + i++;
>> and also, i tried this in gcc, answer was 20, > so what the sequence points
>> for evaluation of something like i++ + i++ ???
> The semicolon at the end of the statement. There are no sequence
> points within the statement.
>
> It is even possible for the answer to be 21.

It's possible for anything to happen, a could be '42', or it could be
'elephant'. My point being that it's not a matter of the compiler
choosing two valid outcomes, *any* outcome is equally valid.
> Please never write actual programs this way. The debugging job might
> fall on me or some other busy person. ;-)
>
>> 2.a = i++; is not defined in the language........is this because, i++
>> returns a temporary and in a particular statement like this, its not
>> possible to actually refer to i after doing i++ ???
>
> Possible? absolutely. Meaningful or recommended? absolutely NOT.
> There is no sequence point across '=' either. Therefore the result
> could end up at either the original 'i' location or at 'i+1'.

Or any other location; again this is not as simple as the compiler
choosing between 'i' or 'i+1'.

>>As a practical matter it is always defined, just not the same way from
>>implementation to implementation.
><snip>
>No, the behaviour is undefined. Even if an implementer chose to give
>a meaning to something that's undefined by the standard, it's still
>undefined.

I'll admit that I was being excessively cute with my answer. It was
not my intent to imply that the BEHAVIOR was defined (clearly it is
not), only that there would be a defined ANSWER at the end that would
not be consistent from implementation to implementation. This stands
in opposition to say x / 0 where depending on the state of floating
point exceptions might not produce any ANSWER at all (division by zero
being mathematically undefined) where "as a practical matter" i++ + i++
is just ambiguous. Still its bad, bad, bad...

>Regardless of whether or not it does anything on a particular platform
>does not make it defined (practically or not). It is undefined
>behavior, plain and simple.

I'm well aware that the BEHAVIOR is undefined. I was gently mocking
and clarifying the imprecise way the question was phrased (e.g. is
"this" defined). There is a definite lack of antecedant here (the
'this' is question could refer to behavior or simply the existence of
an answer within the domain of integers)

While it is true that once one strays outside a language's definition
that anything is "possible", there is more to it than that - hence the
disclaimer "as a PRACTICALmatter" - it's a hint that I am describing
how typical implementations are apt to behave not what the standard
guarantees.. In the first example, the values 20, 21, or 22 are the
most likely to be encountered. In the second example, the locations i,
or i+1 are the most likely targets of assignment though it is POSSIBLE
that an invalid memory reference could occur if memory addresses are
being generated for a RISC or other esoteric addressing architecture
with code optimization, though I have never personally encountered such
a situation. (Fortunately I don't run into this kind of code very
often either and I'm certainly not in the habit of producing it.)

BTW, In the first example, it is quite impossible for the value
'elephant' to result since clearly that is not in the domain of
integers (the declared datatype being int) -- ;-)

I think it useful to distinguish between a result that is defined
(i.e. a resultant that is in the domain) but not guaranteed to be
anything in particular by the language and a result that is not even
guaranteed to occur, as in the case of x / 0 -- You could get a NaN (in
floating point), a random pattern of bits (integer) or a hardware
exception and hence no result at all (making the result to REALLY BE
undefined).

I also think that while it's useful to remind beginners that undefined
BEHAVIOR means just that, it is also true that implementations will AS
A PRACTICAL MATTER tend to behave in certain characteristic ways when
boundaries are breeched. When we are debugging a large program
(especially one containing a lot of code we did not personally write)
these characteristics are often the only thing we can observe as we try
to work backward to the underlying issue

"Novitas" <> writes:
>>>As a practical matter it is always defined, just not the same way from
>>>implementation to implementation.
>
>><snip>
>
>>No, the behaviour is undefined. Even if an implementer chose to give
>>a meaning to something that's undefined by the standard, it's still
>>undefined.
>
> I'll admit that I was being excessively cute with my answer. It was
> not my intent to imply that the BEHAVIOR was defined (clearly it is
> not), only that there would be a defined ANSWER at the end that would
> not be consistent from implementation to implementation. This stands
> in opposition to say x / 0 where depending on the state of floating
> point exceptions might not produce any ANSWER at all (division by zero
> being mathematically undefined) where "as a practical matter" i++ + i++
> is just ambiguous. Still its bad, bad, bad...

Please provide proper attributions so we can tell who wrote what.
Even the groups.google.com interface will do this for you if you
follow the standard advice:

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

The code in question was;

int i = 10;
int a = i++ + i++;

This is not merely ambiguous, it invokes undefined behavior. This
means that there can be no defined answer. As far as the language is
concerned, it could store any value in a (20, 21, 22, 137, 0xdeadbeef,
or a banana split), or it could fail to store any value in a, or it
could cause the program to abort, or it could cause the memory chip
holding the value of a to explode into a colorful mist of adverbs, or,
classically, it could make demons fly out your nose. It is undefined
behavior in exactly the same sense that x/0 is undefined behavior.

Now it's likely that on most real-world implementations, the result
will be that a takes on the value 20 or 21; after all, those are just
two of the infinitely many possible consequences of undefined
behavior.

It's also possible that a sufficiently clever compiler will recognize
the undefined behavior (though it's not required to) and refuse to
compile the program.

That's what the standard says, but it doesn't quite explain why.
There are two answers to that. (Well, three if you count "because the
standard says so", but that's not very satisfying.)

One is that there are probably some things defined as undefined
behavior that don't really need to be. The standard *could* place
tighter constraints on some things. The problem is that it's not
clear just what those things are. If the committee had taken the time
to go through every instance of undefined behavior and argue about
whether it can be "fixed", they wouldn't have had time to produce the
standard.

Another has to do with optimization. An optimizer is typically an
optional phase of a multi-pass compiler; it takes as input some
intermediate form of the program, and produces as output the same
intermediate form, but with transformations that presumably make it
more efficient. An optimizer is constrained by correctness
requirements; it can't take a valid program that does one thing and
turn it into a program that does something else. But in proving that
a transformation can't break the program, the optimizer is allowed to
assume that the program doesn't invoke undefined behavior (because if
it does, the program is already broken anyway, and breaking it further
is ok). If that assumption is incorrect, anything can happen.

The standard deliberately allows optimizers to mangle bad code (code
that invokes undefined behavior) so they can do as good a job as
possible on good code (code that doesn't invoke undefined behavior).

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Novitas wrote:
>
[... referring to "int i=10;int a = i++ + i++;" ...]
> >>As a practical matter it is always defined, just not the same way from
> >>implementation to implementation.
>
> ><snip>
>
> >No, the behaviour is undefined. Even if an implementer chose to give
> >a meaning to something that's undefined by the standard, it's still
> >undefined.
>
> I'll admit that I was being excessively cute with my answer. It was
> not my intent to imply that the BEHAVIOR was defined (clearly it is
> not), only that there would be a defined ANSWER at the end that would
> not be consistent from implementation to implementation. This stands
> in opposition to say x / 0 where depending on the state of floating
> point exceptions might not produce any ANSWER at all (division by zero
> being mathematically undefined) where "as a practical matter" i++ + i++
> is just ambiguous. Still its bad, bad, bad...

Who says that there is a defined answer? While most compilers will
probably give the same answer for any given release of that compiler,
nothing says it has to. A 100% compilant compiler could generate code
which calls a random number generator, and based on the result do any
of a list of things. The code:

int a = i++ + i++;

could generate the equivalent of this code and still be 100% ANSI
compliant:

On 2005-09-14 17:19:43 -0400, "Novitas" <> said:
>>> As a practical matter it is always defined, just not the same way from
>>> implementation to implementation.
>
>> <snip>
>
>> No, the behaviour is undefined. Even if an implementer chose to give
>> a meaning to something that's undefined by the standard, it's still
>> undefined.
>
> I'll admit that I was being excessively cute with my answer. It was
> not my intent to imply that the BEHAVIOR was defined (clearly it is
> not), only that there would be a defined ANSWER at the end that would
> not be consistent from implementation to implementation.

There needn't be any answer at all. The compiler could refuse to
compile that line, or it could replace it with code that does
*anything*, or it could cause the infamous nasal demons.

On 2005-09-14 17:51:57 -0400, "Novitas" <> said:
> BTW, In the first example, it is quite impossible for the value
> 'elephant' to result since clearly that is not in the domain of
> integers (the declared datatype being int) -- ;-)

Not so, imagine sizeof(int) == 8, and 'elephant', as an integer
character constant, is a representable, although implementation
defined, value ;-)
> I think it useful to distinguish between a result that is defined
> (i.e. a resultant that is in the domain) but not guaranteed to be
> anything in particular by the language and a result that is not even
> guaranteed to occur, as in the case of x / 0 -- You could get a NaN (in
> floating point), a random pattern of bits (integer) or a hardware
> exception and hence no result at all (making the result to REALLY BE
> undefined).

Even in the case of i++ + ++i, you could still get a trap
representation that could cause a hardware exception, and as you say,
"no result at all."

Kenneth Brody <> writes:
> Novitas wrote:
>>
> [... referring to "int i=10;int a = i++ + i++;" ...]
>
>> >>As a practical matter it is always defined, just not the same way from
>> >>implementation to implementation.
>>
>> ><snip>
>>
>> >No, the behaviour is undefined. Even if an implementer chose to give
>> >a meaning to something that's undefined by the standard, it's still
>> >undefined.
[snip]
> Who says that there is a defined answer? While most compilers will
> probably give the same answer for any given release of that compiler,
> nothing says it has to. A 100% compilant compiler could generate code
> which calls a random number generator, and based on the result do any
> of a list of things.

Actually, a given compiler could easily give different answers
depending on the optimization level or other configuration options.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!