By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,918 Members | 2,246 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,918 IT Pros & Developers. It's quick & easy.

i = i++ for class types...still undefined?

P: n/a
I was recently reading an article about sequence points that used the canonical

i = i++;

as an illustration of modifying a variable multiple times between sequence
points.

Curiously the article did not indicate the type of i.

Is it fair to say that if i was an instance of a class type that overloaded
operator++(int) that we are no longer dealing with undefined behavior?

My reasoning is that in that case

i = i++;

is actually

i.operator=(i.operator++(0));

and i is not really being modified multiple times between sequence points.

Can anyone shed some light on this?


Jul 22 '05 #1
Share this Question
Share on Google+
24 Replies


P: n/a
"DaKoadMunky" <da*********@aol.com> wrote in message
news:20***************************@mb-m02.aol.com...
I was recently reading an article about sequence points that used the canonical
i = i++;

as an illustration of modifying a variable multiple times between sequence
points.

Curiously the article did not indicate the type of i.

Is it fair to say that if i was an instance of a class type that overloaded operator++(int) that we are no longer dealing with undefined behavior?

My reasoning is that in that case

i = i++;

is actually

i.operator=(i.operator++(0));

and i is not really being modified multiple times between sequence points.

Can anyone shed some light on this?


It sounds like you don't need any light shed on this. It's true that some
of the undefined behavior that can occur with built-in types does not occur
with class types even when operator overloading makes the code look similar.
In the above code, the function calls create sequence points that would not
be present if i had been of type int, so there is no undefined behavior.
Assuming that i's operator++ and operator= are defined the same as int's,
first the value is incremented and then the old value is passed to
operator=, leaving i unchanged.

--
David Hilsee
Jul 22 '05 #2

P: n/a
DaKoadMunky wrote:
I was recently reading an article about sequence points that used the canonical
i = i++;

as an illustration of modifying a variable multiple times between sequence
points.

Curiously the article did not indicate the type of i.

Is it fair to say that if i was an instance of a class type that overloaded operator++(int) that we are no longer dealing with undefined behavior?

My reasoning is that in that case

i = i++;

is actually

i.operator=(i.operator++(0));

and i is not really being modified multiple times between sequence points.
Nice question.
Can anyone shed some light on this?


I'm not a language lawyer, and I don't play one on teevee...

....But aren't there perforce sequence points inside both i.operator++() and
i.operator=()?

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #3

P: n/a
DaKoadMunky posted:
My reasoning is that in that case

i = i++;

is actually

i.operator=(i.operator++(0));

and i is not really being modified multiple times between sequence
points.

Can anyone shed some light on this?


Well first thing:

signed main()
{
int i = 5;

i = i++;

std::cout << i;
}

I wouldn't call the above undefined behaviour, more like implementation-
defined behaviour.

signed main()
{
SomeClass obj;

obj = obj++;
}
If obj = obj++ becomes:

obj.operator=( i.operator++(0) );

then you are right in saying that what happens is clearly defined by the
Standard and is not implementation-defined at all.

That's what it looks like to me.
-JKop
Jul 22 '05 #4

P: n/a

"JKop" <NU**@NULL.NULL> wrote in message news:92******************@news.indigo.ie...

I wouldn't call the above undefined behaviour, more like implementation-
defined behaviour.

It's not implementation-defined. The standard doesn't place any restrictions
on what happens here. In fact, most implementations do various things with
that statement based on the context, level of optimization, etc...

Jul 22 '05 #5

P: n/a
JKop wrote:

signed main()
{
int i = 5;

i = i++;

std::cout << i;
}

I wouldn't call the above undefined behaviour, more like implementation-
defined behaviour.


The language definition disagrees with you. The behavior of that code is
undefined.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #6

P: n/a
Pete Becker posted:
JKop wrote:

signed main()
{
int i = 5;

i = i++;

std::cout << i; }

I wouldn't call the above undefined behaviour, more like implementation- defined behaviour.

The language definition disagrees with you. The behavior

of that code is undefined.


With undefined behaviour, anything can happen.

But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.

Neither of these possibilities result in undefined
behaviour.

-JKop
Jul 22 '05 #7

P: n/a
JKop wrote:

Pete Becker posted:
JKop wrote:

signed main()
{
int i = 5;

i = i++;

std::cout << i; }

I wouldn't call the above undefined behaviour, more like implementation- defined behaviour.

The language definition disagrees with you. The behavior

of that code is
undefined.


With undefined behaviour, anything can happen.


With undefined behavior the language definition imposes no requirements.

But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.

Neither of these possibilities result in undefined
behaviour.


The language definition disagrees with you. The behavior is undefined.
Speculating on what a compiler might do doesn't change that.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #8

P: n/a
Pete Becker posted:
But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.

Neither of these possibilities result in undefined behaviour.


The language definition disagrees with you. The behavior is undefined.
Speculating on what a compiler might do doesn't change that.


signed main()
{
int i = 5;

i = i++;
}
If we're to be pedantic, then you are right, nothing in particular will
happen in the above.

If we're to be realistic, then I am right, there's two possible things that
may happen.

Overall, you think that you are right and I think that I am right. There's
no more arguments so it look like end of conversation.
-JKop
Jul 22 '05 #9

P: n/a
JKop wrote:

Pete Becker posted:
But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.

Neither of these possibilities result in undefined behaviour.


The language definition disagrees with you. The behavior is undefined.
Speculating on what a compiler might do doesn't change that.


signed main()
{
int i = 5;

i = i++;
}

If we're to be pedantic, then you are right, nothing in particular will
happen in the above.


Perhaps you have forgotten what you said originally:

I wouldn't call the above undefined behaviour, more like
implementation-defined behaviour.

The terms "undefined behavior" and "implementation defined behavior"
have specific meanings set out in the language definition. When you use
technical terms it is reasonable for people to assume that you intend
them to be interpreted according to their technical meaning. If you do
not intend that, don't use technical terms.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #10

P: n/a

"JKop" <NU**@NULL.NULL> wrote in message news:wZ******************@news.indigo.ie...
With undefined behaviour, anything can happen.

But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.

Neither of these possibilities result in undefined
behaviour.

Both of them are undefined behavior. Implementation
defined behavior means that the implantation is REQUIRED
to tell you which one will happen. No compiler that I know
of ever tells you what i = i++ will return. On most it even
depends on the context. Even if the implementation only
generated one of the above cases, it's under no requirement
to do so consistently.
Jul 22 '05 #11

P: n/a
"JKop" <NU**@NULL.NULL> wrote in message
news:Zf******************@news.indigo.ie...
<snip>
If we're to be pedantic, then you are right, nothing in particular will
happen in the above.

If we're to be realistic, then I am right, there's two possible things that may happen.

Overall, you think that you are right and I think that I am right. There's
no more arguments so it look like end of conversation.


This is covered in the C FAQ (http://www.eskimo.com/~scs/C-faq/top.html).
See section 3, questions 1 through 9.

--
David Hilsee
Jul 22 '05 #12

P: n/a
JKop wrote:
Pete Becker posted:
But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.

Neither of these possibilities result in undefined behaviour.

The language definition disagrees with you. The behavior is
undefined. Speculating on what a compiler might do doesn't change
that.


signed main()
{
int i = 5;

i = i++;
}
If we're to be pedantic, then you are right, nothing in particular
will happen in the above.


You may want to call it "pedantic", but the C++ standard claerly defines
what undefined behavour is and what implementation defined behavour is.
There is no room for interpretation.
If we're to be realistic, then I am right, there's two possible things
that may happen.
The compiler/CPU might also do some special optimziation tricks that
doesn't work correctly without that sequence point (which is actually
the reason for that rule). Do you know _every_ implementation of C++
and are you sure that none of them ever does something else than one of
those two things you think it does?
Overall, you think that you are right and I think that I am right.
Actually, I'm not quite sure whether anyone of you is right, but I know
that you are not :-)
The standard says:

Except where noted, the order of evaluation of operands of indiviual
operators and subexpressions of individual expressions, and the order
in which side effects take place, is unspecified. Between the previous
and 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. The requirements of this paragraph shall be met for each
allowable ordering of the subexpressions for a full expression;
otherwise the bahavor is undefined. [Example:

i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9

i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented

--end example]

What I don't understand about that is the example. While the actual text
speaks of undefined behavour, the example instead says that it's
unspecified.
There's no more arguments so it look like end of conversation.


This isn't really a matter of opinion.

Jul 22 '05 #13

P: n/a
On Sun, 08 Aug 2004 09:27:44 -0400, Pete Becker <pe********@acm.org>
had a scratch and wrote:
JKop wrote:

signed main()
{
int i = 5;

i = i++;

std::cout << i;
}

I wouldn't call the above undefined behaviour, more like implementation-
defined behaviour.


The language definition disagrees with you. The behavior of that code is
undefined.


Undefined behavior generally refers to erroneous logic. The above is
simply implementation specific, you know.

cf. unspecified behaviors.

=====================

Pussie sHaveMo
reFunMeow MeowMeowPus
siesHaveMore FunMeowMeowMeo
wPussiesHaveMo reFunMeowMeowMeo
wPussiesHaveMor eFunMeowMeowMeowP
ussiesHaveMoreFu nMeowMeowMeowPussi
esHaveMoreFunMeo wMeowMeowPussiesHav
eMoreFunMeowMeowM eowPussiesHaveMor
eFunMeowMeowMeowP ussiesHaveMoreFunM
eowMeowMeowPussie sHaveMoreFunMeowMe owMeowPus
siesHaveM oreFunMeowMeowMe owPussiesHaveMore FunMeowMeowMe
owPussiesHave MoreFunMeowMeowM eowPussiesHaveM oreFunMeowMeowM
eowPussiesHaveM oreFunMeowMeow MeowPussiesHa veMoreFunMeowMeow
MeowPussiesHave MoreFunMeow MeowMeow PussiesHaveMoreFun
MeowMeowMeowPussi esHa veMoreFunMeowMeowMe
owPussiesHaveMoreF unMeowMeowM eowPussiesHaveMoreFu
nMeowMeowMeowPussie sHaveMoreFunMe owMeowMeowPussiesHav
eMoreFunMeowMeowMeo wPussiesHaveMoreFu nMeowMeowMeowPussie
sHaveMoreFunMeowMeo wMeowPussiesHaveMoreFu nMeowMeowMeowPussi
esHaveMoreFunMeowM eowMeowPussiesHaveMoreFu nMeowMeowMeowPuss
iesHaveMoreFunMe owMeowMeowPussiesHaveMoreFu nMeowMeowMeowP
ussiesHaveMor eFunMeowMeowMeowPussiesHaveMore FunMeowMeow
MeowPussi esHaveMoreFunMeowMeowMeowPussiesHave MoreF
unMe owMeowM eowPuss
iesHave MoreF unMeowMeowM
eowPussies Ha veMoreFunMeo
wMeowMeowP us si esHaveMoreFu
nMeowMeowM eow Pus siesHaveMore
FunMeowMeo wMeow Pussi esHaveMoreFu
nMeowMeow MeowPu ssiesH aveMoreFun
Meow MeowMeow Pussie
sHaveMoreFunMeowMeowMeowPussiesHaveM
oreFunMeowMeowMeowPussiesHaveMo
reFunMeowMeowMeowPussies
Jul 22 '05 #14

P: n/a
On Sun, 08 Aug 2004 10:03:24 -0400, Pete Becker <pe********@acm.org>
had a scratch and wrote:
JKop wrote:

Pete Becker posted:
>> But with the above code, there's but two possibilities:
>>
>> 1) i ends up with the value 5.
>> 2) i ends up with the value 6.
>>
>> Neither of these possibilities result in undefined behaviour.
>>
>
> The language definition disagrees with you. The behavior is undefined.
> Speculating on what a compiler might do doesn't change that.


signed main()
{
int i = 5;

i = i++;
}

If we're to be pedantic, then you are right, nothing in particular will
happen in the above.


Perhaps you have forgotten what you said originally:

I wouldn't call the above undefined behaviour, more like
implementation-defined behaviour.

The terms "undefined behavior" and "implementation defined behavior"
have specific meanings set out in the language definition. When you use
technical terms it is reasonable for people to assume that you intend
them to be interpreted according to their technical meaning. If you do
not intend that, don't use technical terms.

You should know.

=====================

Pussie sHaveMo
reFunMeow MeowMeowPus
siesHaveMore FunMeowMeowMeo
wPussiesHaveMo reFunMeowMeowMeo
wPussiesHaveMor eFunMeowMeowMeowP
ussiesHaveMoreFu nMeowMeowMeowPussi
esHaveMoreFunMeo wMeowMeowPussiesHav
eMoreFunMeowMeowM eowPussiesHaveMor
eFunMeowMeowMeowP ussiesHaveMoreFunM
eowMeowMeowPussie sHaveMoreFunMeowMe owMeowPus
siesHaveM oreFunMeowMeowMe owPussiesHaveMore FunMeowMeowMe
owPussiesHave MoreFunMeowMeowM eowPussiesHaveM oreFunMeowMeowM
eowPussiesHaveM oreFunMeowMeow MeowPussiesHa veMoreFunMeowMeow
MeowPussiesHave MoreFunMeow MeowMeow PussiesHaveMoreFun
MeowMeowMeowPussi esHa veMoreFunMeowMeowMe
owPussiesHaveMoreF unMeowMeowM eowPussiesHaveMoreFu
nMeowMeowMeowPussie sHaveMoreFunMe owMeowMeowPussiesHav
eMoreFunMeowMeowMeo wPussiesHaveMoreFu nMeowMeowMeowPussie
sHaveMoreFunMeowMeo wMeowPussiesHaveMoreFu nMeowMeowMeowPussi
esHaveMoreFunMeowM eowMeowPussiesHaveMoreFu nMeowMeowMeowPuss
iesHaveMoreFunMe owMeowMeowPussiesHaveMoreFu nMeowMeowMeowP
ussiesHaveMor eFunMeowMeowMeowPussiesHaveMore FunMeowMeow
MeowPussi esHaveMoreFunMeowMeowMeowPussiesHave MoreF
unMe owMeowM eowPuss
iesHave MoreF unMeowMeowM
eowPussies Ha veMoreFunMeo
wMeowMeowP us si esHaveMoreFu
nMeowMeowM eow Pus siesHaveMore
FunMeowMeo wMeow Pussi esHaveMoreFu
nMeowMeow MeowPu ssiesH aveMoreFun
Meow MeowMeow Pussie
sHaveMoreFunMeowMeowMeowPussiesHaveM
oreFunMeowMeowMeowPussiesHaveMo
reFunMeowMeowMeowPussies
Jul 22 '05 #15

P: n/a
Rolf Magnus wrote:

otherwise the bahavor is undefined. [Example:

i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9

i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented

--end example]

What I don't understand about that is the example. While the actual text
speaks of undefined behavour, the example instead says that it's
unspecified.


That has been fixed. The current draft in boht places says that the
behavior is undefined.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #16

P: n/a
Bradley Bungmunch wrote:

On Sun, 08 Aug 2004 09:27:44 -0400, Pete Becker <pe********@acm.org>
had a scratch and wrote:
JKop wrote:

signed main()
{
int i = 5;

i = i++;

std::cout << i;
}

I wouldn't call the above undefined behaviour, more like implementation-
defined behaviour.


The language definition disagrees with you. The behavior of that code is
undefined.


Undefined behavior generally refers to erroneous logic. The above is
simply implementation specific, you know.


The language definition says that the behavior of that code is
undefined.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #17

P: n/a
This might be a question for another posting or group, but here goes...

int n = 0;

n = n++; //Undefined due to multiple modifications between SP

If this is undefined why even allow it to compile?

I am aware that not all actions leading to undefined behavior can be caught at
compile-time but in this case it seems that it could.

What is the value in allowing this to be syntatically correct yet saying
anything at all could happen?
Jul 22 '05 #18

P: n/a
On Sun, 08 Aug 2004 13:34:20 GMT, JKop <NU**@NULL.NULL> wrote in
comp.lang.c++:
Pete Becker posted:
JKop wrote:

signed main()
{
int i = 5;

i = i++;

std::cout << i; }

I wouldn't call the above undefined behaviour, more like implementation- defined behaviour.


The language definition disagrees with you. The behavior

of that code is
undefined.


With undefined behaviour, anything can happen.

But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.

Neither of these possibilities result in undefined
behaviour.


Enough. *plonk*

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jul 22 '05 #19

P: n/a
Jack Klein posted:
On Sun, 08 Aug 2004 13:34:20 GMT, JKop <NU**@NULL.NULL> wrote in comp.lang.c++:
Pete Becker posted:
> JKop wrote:
>>
>> signed main()
>> {
>> int i = 5;
>>
>> i = i++;
>>
>> std::cout << i; }
>>
>> I wouldn't call the above undefined behaviour, more like >> implementation- defined behaviour.
>>
>
> The language definition disagrees with you. The behavior of that > code is undefined.
>
With undefined behaviour, anything can happen.

But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.

Neither of these possibilities result in undefined

behaviour.
Enough. *plonk*

Your post is OFF-TOPIC here.

Have you got kids? Did you learn that from them? Or do you
intend to teach it to them?
-JKop
Jul 22 '05 #20

P: n/a
DaKoadMunky wrote:
This might be a question for another posting or group, but here goes...

int n = 0;

n = n++; //Undefined due to multiple modifications between SP

If this is undefined why even allow it to compile?
Compilers are not required to specify what happens to undefined behavior.
When the behavior is easy to detect, the compiler might bounce it, or warn
about it.

When the behavior is hard to detect, a compiler

And a compiler might just produce opcodes without bothering to warn
anything, even if it's easy to detect.

Consider:

SimCity & aCity = *(SimCity *) NULL;

Null references are undefined. The indefinity occurs at the left star *.
However, if a compiler added a check for this situation, it would commit to
checking where the right argument is less obvious. Checking at runtime would
slow down millions of innocent and correct dereferences. So the compiler
compiles the well-formed code, and lets the programmer live with the
consequences of their actions.
What is the value in allowing this to be syntatically correct yet saying
anything at all could happen?


As a false convenience for naive programmers.

But what if n and m were references to the same integer. A compiler might
not easily be able to check that. If it can't check all forms of a
situation, it won't check any, including the obvious ones.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces

Jul 22 '05 #21

P: n/a
DaKoadMunky wrote:

This might be a question for another posting or group, but here goes...

int n = 0;

n = n++; //Undefined due to multiple modifications between SP

If this is undefined why even allow it to compile?


Because that's a simple example of a more complicated problem:

void f(int& a, int& b)
{
a = b++;
}

int i = 3;
f(i,i);

Generally speaking this problem isn't easy to recognize, so the standard
doesn't require a diagnostic (the standard never requires that something
not compile -- that's the hook for conforming extensions: issue a
diagnostic then do the extension).

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #22

P: n/a
JKop <NU**@NULL.NULL> wrote:
Pete Becker posted:
But with the above code, there's but two possibilities:

1) i ends up with the value 5.
2) i ends up with the value 6.
Why would you think that?
Neither of these possibilities result in undefined behaviour.
signed main()
{
int i = 5;

i = i++;
}

If we're to be realistic, then I am right, there's two possible things that
may happen.
I've heard of a compiler that results in i == 11, and of one that
causes a segmentation fault, for that code
Overall, you think that you are right and I think that I am right. There's
no more arguments so it look like end of conversation.


You left out one minor detail: the standard (and the C faq and the C++ faq)
say that you are wrong and Pete is right.
Jul 22 '05 #23

P: n/a
Old Wolf wrote:

JKop <NU**@NULL.NULL> wrote:
Pete Becker posted:


Please be more careful with attributions. I didn't write anything in the
text you included.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #24

P: n/a

"DaKoadMunky" <da*********@aol.com> wrote in message news:20***************************@mb-m27.aol.com...
This might be a question for another posting or group, but here goes...

int n = 0;

n = n++; //Undefined due to multiple modifications between SP

If this is undefined why even allow it to compile?

In this case a compiler could recognize the undefined behavior and issue
a diagnostic. It is free to do so. However with a more complex expression:

int x;
int* p1 = &x;
int* p2 = &x;

// obfuscating pointer manipulations

*p1 = *p2++;

etc... might not be detectable at compile time.

Jul 22 '05 #25

This discussion thread is closed

Replies have been disabled for this discussion.