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

operation on `x' may be undefined?

P: n/a
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?

TIA
Nov 15 '05 #1
Share this Question
Share on Google+
30 Replies


P: n/a

jimjim wrote:
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?

TIA


Nice compiler warning! Anyway, see the FAQ:

http://www.eskimo.com/~scs/C-faq/q3.2.html

-David

Nov 15 '05 #2

P: n/a
jimjim wrote:
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?

TIA


Why don't you read the FAQ before posting something that has been asked
and answered thounsands of times before?

Nov 15 '05 #3

P: n/a
jimjim wrote:
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?


(a) Read the FAQ.

(b) Given the compiler warning, why are you surprised at the output?

--
Chris "electric hedgehog" Dollin
Stross won one! Farah won one! Langford won TWO!
Nov 15 '05 #4

P: n/a

jimjim wrote:
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?

TIA


You're running into two issues:

1. Undefined behavior -- you are attempting to modify the value of an
object more than once between sequence points, and the Standard imposes
no requirement on how to handle that behavior. Basically, any
expression of the forms:

i = i++;
j = k++ * k++;
foo(i,i++,--i);

invoke undefined behavior. Read up on the semantics of the "++" and
"--" operators in an *authoritative* reference (the Standard would
obviously be one, but also K&R2 or H&S5); they don't work the way most
people think they should.

2. Order of evaluation -- AFAIK, there's no requirement that
expressions in a function parameter list be evaluated in any particular
order. At first blush, it *looks* like the arguments were evaluated
from right to left (if x = 1, then x++ evaluates to 1, with the side
effect that x == 2, and ++x evaluates to 3, with the side effect that x
== 3), but given that you've invoked undefined behavior the actual
reason may be something else entirely.

Nov 15 '05 #5

P: n/a
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

jimjim wrote:
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Because the order of evaluation of function arguments is not defined by
the standard, and, in the evaluation of the arguments to your printf()
function call, the value of x at any one point depends on the value of x
at some other point
Why when run the output is: "3 2 1"?


Because, with "undefined operations", /any/ result is a valid result.
- --

Lew Pitcher, IT Specialist, Enterprise Data Systems
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)

iD8DBQFC+im3agVFX4UWr64RAlp4AKCPdVuxVcwMuLj8c2ARKN yfhC8ZkgCeK21z
X9885DRA8ph6o5JhLCo0QEI=
=277u
-----END PGP SIGNATURE-----
Nov 15 '05 #6

P: n/a
jimjim wrote:
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?


It all comes down to the concept of *sequence points*. 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).

See http://publications.gbdirect.co.uk/c...ce_points.html
August
Nov 15 '05 #7

P: n/a
> (b) Given the compiler warning, why are you surprised at the output?

Given that my compiler is the gcc, could you have a guess why is it 3 2 1
and not 1 2 3? ;-)
Nov 15 '05 #8

P: n/a
great thx for the help!
Nov 15 '05 #9

P: n/a
> Given that my compiler is the gcc, could you have a guess why is it 3 2 1
and not 1 2 3? ;-)

I am happy that others in this group are happy to provide **answers** and
not just waffling
Nov 15 '05 #10

P: n/a
"jimjim" <ne*****@blueyonder.co.uk> writes:
(b) Given the compiler warning, why are you surprised at the output?

Given that my compiler is the gcc, could you have a guess why is it 3 2 1
and not 1 2 3? ;-)


If I were more familiar with the details of gcc's code generation, I
might, but such a guess would not be useful. The code invokes
undefined behavior, which means it could behave differently with the
next release of gcc or with the phase of the moon.

The code is broken. The only appropriate thing to do is fix it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 15 '05 #11

P: n/a
jimjim wrote:
Given that my compiler is the gcc, could you have a guess why is it 3 2 1
and not 1 2 3? ;-)


I am happy that others in this group are happy to provide **answers** and
not just waffling

Ignorance is bliss I suppose. I can't tell what you are referring to as
waffling.

printf("%d %d %d\n", ++x, x, x++);

I'll guess that someone told you that treating x this way is stupid and
that you should read a C book or at least the FAQ.

If you are unwilling to do that and want me to look it up and quote it
to you, you've got the wrong guy.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 15 '05 #12

P: n/a
jimjim wrote:
Given that my compiler is the gcc, could you have a guess why is it
3 2 1 and not 1 2 3? ;-)

I am happy that others in this group are happy to provide answers and
not just waffling

*plonk*

Brian
Nov 15 '05 #13

P: n/a
John has given a guess:
2. Order of evaluation -- AFAIK, there's no requirement that
expressions in a function parameter list be evaluated in any particular
order. At first blush, it *looks* like the arguments were evaluated
from right to left (if x = 1, then x++ evaluates to 1, with the side
effect that x == 2, and ++x evaluates to 3, with the side effect that x
== 3), but given that you've invoked undefined behavior the actual
reason may be something else entirely.


I think this is caused by the Function Calling Conventions used by your
complier.
maybe you compiler set a prefix "_cdecl" for every standard function.
(you could find that by opening a header file).
there are some rules about _cdecl, more about it, there is a webpage:
http://www.programmers-corner.com/tutorial/16

_cdecl
Arguments Passed from Right to Left
Calling Function Clears the Stack
‘this’ pointer is passed via stack last in case of Programs
using OOP
Functions using _cdecl are preceded by an “_”

so, the first "Arguments Passed from Right to Left " one is the key to
your problem.

Nov 15 '05 #14

P: n/a
On 10 Aug 2005 18:42:26 -0700, ke******@hotmail.com wrote in
comp.lang.c:
John has given a guess:
2. Order of evaluation -- AFAIK, there's no requirement that
expressions in a function parameter list be evaluated in any particular
order. At first blush, it *looks* like the arguments were evaluated
from right to left (if x = 1, then x++ evaluates to 1, with the side
effect that x == 2, and ++x evaluates to 3, with the side effect that x
== 3), but given that you've invoked undefined behavior the actual
reason may be something else entirely.
I think this is caused by the Function Calling Conventions used by your
complier.


You are wrong to think that.
maybe you compiler set a prefix "_cdecl" for every standard function.
(you could find that by opening a header file).
there are some rules about _cdecl, more about it, there is a webpage:
http://www.programmers-corner.com/tutorial/16


Why do you think a web page that says it specifically and only refers
to one version of one compiler has anything to do with the language
standard, or even any other compiler?

The code is broken because it does something that the C standard says
it undefined behavior, a very specific term. Whatever the program
actually does is irrelevant and off-topic here. The C language does
not know or care, and anything the program does is just as right or
just as wrong as anything else.

--
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
Nov 15 '05 #15

P: n/a
Jack Klein <ja*******@spamcop.net> writes:
[...]
The code is broken because it does something that the C standard says
it undefined behavior, a very specific term. Whatever the program
actually does is irrelevant and off-topic here. The C language does
not know or care, and anything the program does is just as right or
just as wrong as anything else.


On the other hand, it can sometimes be useful to know what a
particular compiler is likely to do when confronted with undefined
behavior. Sometimes fixing the code isn't an option, or requires a
tremendous amount of effort; for example, if the code has already been
deployed, and is generally working correctly, the risk of making a
change may exceed the benefit of fixing a possible bug. There may be
other code that incorrectly depends on a the way a particular instance
of undefined behavior is handled; fixing one but not the other can
break a working program, even if it works only by accident.

Also, if I see "void main()", for example, I'm going to want to
correct it, but knowing that most compilers don't actually screw
things up too badly in the presence of "void main()" might tell me
that I need to keep looking elsewhere for the cause of the mysterious
bug I'm seeing.

For the purpose of writing new code, all you really need to know is
that undefined behavior is to be avoided. For the purpose of
understanding the behavior of existing code, knowing some of the
undefined and implementation-specific details can be useful -- as long
as you're aware that the details are undefined and
implementation-specific.

I don't believe that the original poster's situation was one that
calls for this kind of knowledge, though.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 15 '05 #16

P: n/a
> If I were more familiar with the details of gcc's code generation, I
might, but such a guess would not be useful. The code invokes
undefined behavior, which means it could behave differently with the
next release of gcc or with the phase of the moon.


Hi there..thx for the reply

Is the footnote 70 of 6.5.2 that talks about
Nov 15 '05 #17

P: n/a
> If I were more familiar with the details of gcc's code generation, I
might, but such a guess would not be useful. The code invokes
undefined behavior, which means it could behave differently with the
next release of gcc or with the phase of the moon.


Hi there..thx for the reply

Is the footnote 70 of 6.5.2 that talks about undefined behavior?

70) This paragraph renders undefined statement expressions such as
i = ++i + 1;

a[i++] = i;

why does the last expression invoke undefined behavior? The value of i is
changed once (I would have guessed that the initial value of i would have
been stored in a, and then the i++ would have been performed before
proceeding to the next statement in the code.

TIA

P.S: posters should stop making assumptions that newbies can comprenhend
everything they are reading in the FAQ!
Nov 15 '05 #18

P: n/a
jimjim wrote:
Given that my compiler is the gcc, could you have a guess why is it 3 2 1
and not 1 2 3? ;-)

I am happy that others in this group are happy to provide **answers** and
not just waffling


If you're referring to /me/, I provided an answer; I told you to read
the FAQ, which has a clear and detailed discussion on this topic.

--
Chris "electric hedgehog" Dollin
Stross won one! Farah won one! Langford won TWO!
Nov 15 '05 #19

P: n/a
Moreover, http://www.eskimo.com/~scs/C-faq/q11.33.html refers to
implementation-defined.
1. Is implementation-defined stated in particular sections of the Standard?
2. Is there a possibility for an implementation to choose some behavior for
a Standard-specified Undefined behaviour and document it?

as always TIA
Nov 15 '05 #20

P: n/a
> Is the footnote 70 of 6.5.2 that talks about undefined behavior?
oups 6.5,2
Nov 15 '05 #21

P: n/a
jimjim wrote:
70) This paragraph renders undefined statement expressions such as
i = ++i + 1;

a[i++] = i;

why does the last expression invoke undefined behavior? The value of i is
changed once (I would have guessed that the initial value of i would have
been stored in a,
Why not the final value?
and then the i++ would have been performed before
proceeding to the next statement in the code.
The standard says (I paraphrase, correctly I hope) that an object
can be updated at most once between sequence points, and an updated
objects "previous" value can be read only to compute the value to be
stored.

In `a[i++] = i`, `i` is updated, and its value is read (on the RHS)
for a reason other than to determine its new value. BOOM.
P.S: posters should stop making assumptions that newbies can comprenhend
everything they are reading in the FAQ!


I'm not making that assumption. /Asking/ (sensible) questions about
the FAQ entries is fine. Not bothering to read them wouldn't be.

--
Chris "pretty as an airport" Dollin
Nov 15 '05 #22

P: n/a
>>and an updated objects "previous" value can be read only to compute the
value to be stored.


In order to make sure that I understand what you are saying, is the sentence
below equivalent with yours?
If between sequence points an object's value is to be modified , its value
should only be read once.
TIA
Nov 15 '05 #23

P: n/a
jimjim wrote:
and an updated objects "previous" value can be read only to compute the
value to be stored.


In order to make sure that I understand what you are saying, is the sentence
below equivalent with yours?
If between sequence points an object's value is to be modified , its value
should only be read once.


No. For example:

int i = 5;

i = i * i;

is perfectly legal, and the value of i is accessed twice (the compiler
might optimize accesses and remember the value without having to read
it both times, but this is not the point).

The standard says what ir says. If an object is to be modified between
two sequence points, then it can only be written once, and read
accesses must be done in order to compute the new value, and for no
other porpouse.

Now, answering your original question.

a[i] = i++;

This statement invokes undefined behaviour because the value of i is
being accessed for some other porpouse than to compute its new value.

The reason why this is specified to be undefined behaviour is that
specifying certain behaviour would impose lots of constraints on
compiler design without any measurable improvement.

Consider you're designing a compiler and have to decide what to do when
faced with the above expression. There are 3 main tasks you should
consider:

1. Get the value of i.
2. Increment i.
3. Compute the address to which the value must be written
(&a + i * sizeof(a[0]))

This things can be done in whatever order the compiler designers decide
suits best their target architecture. If you perform the operation in
the order in which I've written them, the result would be the same that
if you had written:

a[i + 1] = i;
i++;

(Because i has already been incremented when the compiler computes the
address to wich the data must be written.)

But this is not the only possible way. If you compute the address
first, then the value to be stored, the result would be that of:

a[i] = i;
i++;

Which is probably what was intended in first place.

HTH

Nov 15 '05 #24

P: n/a
> The standard says what ir says. If an object is to be modified between
two sequence points, then it can only be written once, and read
accesses must be done in order to compute the new value, and for no
other porpouse.

This now makes sense to me. thx
Nov 15 '05 #25

P: n/a
"jimjim" <ne*****@blueyonder.co.uk> writes:
If I were more familiar with the details of gcc's code generation, I
might, but such a guess would not be useful. The code invokes
undefined behavior, which means it could behave differently with the
next release of gcc or with the phase of the moon.


Hi there..thx for the reply

[snip]

Please provide attributions. I see you're using Microsoft Outlook
Express, which I'm fairly sure should do this for you. The text
prefixed by ">> " was mine, so it should be preceded by something like

Keith Thompson <ks***@mib.org> writes:

It's easier to follow the discussion when we can see who wrote what.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 15 '05 #26

P: n/a
"jimjim" <ne*****@blueyonder.co.uk> writes:
Moreover, http://www.eskimo.com/~scs/C-faq/q11.33.html refers to
implementation-defined.
1. Is implementation-defined stated in particular sections of the Standard?
Yes. The term "implementation-defined behavior" is defined in C99 3.4.1 as

unspecified behavior where each implementation documents how the
choice is made

If you search for "implementation-defined" in the standard, you'll
find many examples.
2. Is there a possibility for an implementation to choose some behavior for
a Standard-specified Undefined behaviour and document it?


Sure, an implementation can define anything it likes. You should be
careful about depending on such things, though, since they likely
won't work the same way on other implementations.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 15 '05 #27

P: n/a
jimjim wrote:
Moreover, http://www.eskimo.com/~scs/C-faq/q11.33.html refers to
implementation-defined.
1. Is implementation-defined stated in particular sections of the Standard?
As I understand it, implementation defined means that the implementation
is *required* to both define and document the behaviour.
2. Is there a possibility for an implementation to choose some behavior for
a Standard-specified Undefined behaviour and document it?


An implementation can do whatever it wants with undefined behaviour
*including* document what it does (the standard even says it is allowed
to document it). Indeed, this is a "standard" way of extending C.

To quote from the standard:

| 3.4.1
| 1 implementation-defined behavior
| unspecified behavior where each implementation documents how the choice
| is made
| 2 EXAMPLE An example of implementation-defined behavior is the propagation
| of the high-order bit when a signed integer is shifted right.
| 3.4.3
| 1 undefined behavior
| behavior, upon use of a nonportable or erroneous program construct or of
| erroneous data, for which this International Standard imposes no
| requirements
| 2 NOTE Possible undefined behavior ranges from ignoring the situation
| completely with unpredictable results, to behaving during
| translation or program execution in a documented manner characteristic
| of the environment (with or without the issuance of a diagnostic
| message), to terminating a translation or execution (with the
| issuance of a diagnostic message).
| 3 EXAMPLE An example of undefined behavior is the behavior on integer
overflow.
|
| 3.4.4
| 1 unspecified behavior
| use of an unspecified value, or other behavior where this International
| Standard provides two or more possibilities and imposes no further
| requirements on which is chosen in any instance
| 2 EXAMPLE An example of unspecified behavior is the order in which the
| arguments to a function are evaluated.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 15 '05 #28

P: n/a
"jimjim" <ne*****@blueyonder.co.uk> wrote in message
news:q5******************@text.news.blueyonder.co. uk...
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?


Everyone here is quick to post that the code invokes undefined behavior,
but doesn't the following excerpt from the standard explicitly allow it?

7.19.6 Formatted input/output functions
1) The formatted input/output functions shall behave as if there is a
sequence point after
the actions associated with each specifier.
7.19.6.1 The fprintf function

Mark
Nov 15 '05 #29

P: n/a
"Mark" <so***@localbar.com> writes:
"jimjim" <ne*****@blueyonder.co.uk> wrote in message
news:q5******************@text.news.blueyonder.co. uk...
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?


Everyone here is quick to post that the code invokes undefined behavior,
but doesn't the following excerpt from the standard explicitly allow it?

7.19.6 Formatted input/output functions
1) The formatted input/output functions shall behave as if there is a
sequence point after
the actions associated with each specifier.
7.19.6.1 The fprintf function


No, I don't think so. The evaluation of the arguments occurs before
the function is called, and is not part of "the actions associated
with each specifier". The quoted statement contrains the internal
behavior of the functions themselves. It implies that the following
(rather silly) code fragment does not invoke undefined behavior:

int count;
printf("hello%n, world%n\n", &count, &count);

(I'm sure there are non-silly examples, but I can't think of any off
the top of my head.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 15 '05 #30

P: n/a
Mark wrote:
"jimjim" <ne*****@blueyonder.co.uk> wrote in message
news:q5******************@text.news.blueyonder.co. uk...
Hello,

#include <stdio.h>

int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}

Why does the above code when compiled with all warnings it issues: "
warning: operation on `x' may be undefined"?
Why when run the output is: "3 2 1"?


Everyone here is quick to post that the code invokes undefined behavior,
but doesn't the following excerpt from the standard explicitly allow it?

7.19.6 Formatted input/output functions
1) The formatted input/output functions shall behave as if there is a
sequence point after
the actions associated with each specifier.
7.19.6.1 The fprintf function


No. You seem to be reading "actions associated with each specifier" as
"evaluation of each parameter", it means what it says, really. This
keeps things like the following from invoking undefined behavior:

int i;
scanf("%d %d", &i, &i);

If not for that clause, i could be modified twice without an
intervening sequence point. Examples of how this could happen are
probably quite contrived but that is the purpose behind the clause. As
for the fprintf functions, the %n conversion specifier performs writes
to memory as pointed out by the footnote to the clause you quoted.

Robert Gamble

Nov 15 '05 #31

This discussion thread is closed

Replies have been disabled for this discussion.