Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

regarding post-increment behaviour in C

25 views
Skip to first unread message

brij...@my-deja.com

unread,
Jan 19, 2001, 10:33:08 AM1/19/01
to
***Disclaimer : The example given below is bad programming. However i
need to handle it...hence the question ***

The question is concerning post-increment in the following context:
int a[4] ={1,2,3,4};
int i=0;
a[i++] = a[i++] + 10;

All the compilers i tried it on (gcc, VC, Borland C) incremented i
after the whole statement.
So the result was a[]={11,2,3,4}.
I had expected a[] = {1,11,3,4} from reading K&R
I am writing a compiler for C and want to know which of the above
behaviour is expected from a post-increment operator.


Sent via Deja.com
http://www.deja.com/

Christian Bau

unread,
Jan 19, 2001, 11:04:50 AM1/19/01
to

Undefined behavior.

You increment i twice in the same expression, and according to the C
standard this is "undefined behavior". Anything can happen, including the
behavior that you saw, the behavior you expected or your machine crashing.


And why didn't you expect { 12, 2, 3, 4} ?

Joona I Palaste

unread,
Jan 19, 2001, 10:54:49 AM1/19/01
to
brij...@my-deja.com scribbled the following:

This isn't about the post-increment operator, this is about the order
of evaluation of the operands.
Since you're modifying the value of i twice without a sequence point
in between, either of the two results are exactly as much "expected".
Also, equally "expected" behaviour includes incrementing every
variable in the array, flipping all the bits in every variable in the
array, converting all instances of the text string "/usr" in memory
to "fsck", changing the colours of your screen to purple, calling the
police on your modem line and telling them you're being attacked by
a one-eyed Martian wielding a herring while singing "Hi ho, it's off
to work we go", and even weirder stuff.
So... what it all boils to... when writing your compiler, just flip
a coin and use the one of the two behaviours you listed that
corresponds with the coin's face.

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/

"The obvious mathematical breakthrough would be development of an easy way to
factor large prime numbers."
- Bill Gates

Craig Barkhouse

unread,
Jan 19, 2001, 11:55:50 AM1/19/01
to

"Joona I Palaste" <pal...@cc.helsinki.fi> wrote in message
news:949o09$171$2...@oravannahka.helsinki.fi...

> brij...@my-deja.com scribbled the following:
> > ***Disclaimer : The example given below is bad programming. However i
> > need to handle it...hence the question ***
>
> > The question is concerning post-increment in the following context:
> > int a[4] ={1,2,3,4};
> > int i=0;
> > a[i++] = a[i++] + 10;
>
> > All the compilers i tried it on (gcc, VC, Borland C) incremented i
> > after the whole statement.
> > So the result was a[]={11,2,3,4}.
> > I had expected a[] = {1,11,3,4} from reading K&R
> > I am writing a compiler for C and want to know which of the above
> > behaviour is expected from a post-increment operator.
>
> This isn't about the post-increment operator, this is about the order
> of evaluation of the operands.
> Since you're modifying the value of i twice without a sequence point
> in between, either of the two results are exactly as much "expected".

Right.

> Also, equally "expected" behaviour includes incrementing every
> variable in the array, flipping all the bits in every variable in the
> array, converting all instances of the text string "/usr" in memory
> to "fsck", changing the colours of your screen to purple, calling the
> police on your modem line and telling them you're being attacked by
> a one-eyed Martian wielding a herring while singing "Hi ho, it's off
> to work we go", and even weirder stuff.
> So... what it all boils to... when writing your compiler, just flip
> a coin and use the one of the two behaviours you listed that
> corresponds with the coin's face.

Um, no, you got carred away here. If the statement were to invoke undefined
behaviour, you could justifiably jest that these things might happen. That
is not the case here. Section 6.5.2.4 of the draft standard make it clear
that "i++" evaluates to i, with a side effect of incrementing the value of i
by one at some indeterminate time between the previous sequence point and
the next sequence point. The only thing that is undefined is *exactly when*
i gets incremented. If incrementing a variable could have side effects like
the ones you list, then it's safe to say that the behaviour of any program
is undefined.

Christian Bau

unread,
Jan 19, 2001, 11:59:45 AM1/19/01
to
In article <qk_96.34529$7.12...@quark.idirect.com>, "Craig Barkhouse"
<cr...@wanware.com> wrote:

> "Joona I Palaste" <pal...@cc.helsinki.fi> wrote in message
> news:949o09$171$2...@oravannahka.helsinki.fi...
> > brij...@my-deja.com scribbled the following:
> > > ***Disclaimer : The example given below is bad programming. However i
> > > need to handle it...hence the question ***
> >
> > > The question is concerning post-increment in the following context:
> > > int a[4] ={1,2,3,4};
> > > int i=0;
> > > a[i++] = a[i++] + 10;

> Um, no, you got carred away here. If the statement were to invoke undefined


> behaviour, you could justifiably jest that these things might happen. That
> is not the case here. Section 6.5.2.4 of the draft standard make it clear
> that "i++" evaluates to i, with a side effect of incrementing the value of i
> by one at some indeterminate time between the previous sequence point and
> the next sequence point. The only thing that is undefined is *exactly when*
> i gets incremented. If incrementing a variable could have side effects like
> the ones you list, then it's safe to say that the behaviour of any program
> is undefined.

The problem is: i is incremented TWICE without intervening sequence point.

a [i++] += 10;

would be perfectly ok.

Peter Pichler

unread,
Jan 19, 2001, 11:55:16 AM1/19/01
to
brij...@my-deja.com wrote in message <949mnk$hib$1...@nnrp1.deja.com>...

>***Disclaimer : The example given below is bad programming. However i
>need to handle it...hence the question ***
>
>The question is concerning post-increment in the following context:
>int a[4] ={1,2,3,4};
>int i=0;
>a[i++] = a[i++] + 10;

Undefined behaviour, ever heard about such a beast?

>All the compilers i tried it on (gcc, VC, Borland C) incremented i
>after the whole statement.
>So the result was a[]={11,2,3,4}.
>I had expected a[] = {1,11,3,4} from reading K&R

And I expected {42,42,42,42} and deamons flying from my floppy drive.

>I am writing a compiler for C

Then you should know about undefined behaviour. I would never dare to
start writing a C compiler without being able to recite the Standard
backwards when woken up at 3 in the morning.

Peter
--
"...you illiterate puff of insignificant killfile lint." -- Kaz Kylheku


Christian Bau

unread,
Jan 19, 2001, 12:26:07 PM1/19/01
to
In article <949rhk$1t21$1...@forties.sophos.com>, "Peter Pichler"
<pic...@pobox.sk> wrote:

Actually, a compiler writer doesn't need to know about undefined behavior
at all: Whatever code he produces for a[i++] = a[i++] + 10; is correct.

And I think your statement is a bit strong anyway: It is good enough if
you can pull out a copy of the standard from under your pillow, switch the
light on, get your eyes in working order and start reading :-)

Craig Barkhouse

unread,
Jan 19, 2001, 12:38:19 PM1/19/01
to
> > Um, no, you got carred away here. If the statement were to invoke
undefined
> > behaviour, you could justifiably jest that these things might happen.
That
> > is not the case here. Section 6.5.2.4 of the draft standard make it
clear
> > that "i++" evaluates to i, with a side effect of incrementing the value
of i
> > by one at some indeterminate time between the previous sequence point
and
> > the next sequence point. The only thing that is undefined is *exactly
when*
> > i gets incremented. If incrementing a variable could have side effects
like
> > the ones you list, then it's safe to say that the behaviour of any
program
> > is undefined.

> The problem is: i is incremented TWICE without intervening sequence point.

I realize that. I'm agreeing that the incrementations could be done at any
time between the sequence points (re-read my paragraph). What I'm saying
is: The uncertainty in order of events doesn't mean that *anything* could
happen. There are only a few possible outcomes for the statement in
question. Some array element (either a[0] or a[1]) will get assigned a
value equal to 10 plus some other array element (either 11 or 12), depending
on what order the implementation chooses. So any of these values could
result: {11,2,3,4} {12,2,3,4} {1,11,3,4} {1,12,3,4}. I don't see how any
other behaviour is conformant. There are operations that result in
"undefined behaviour" according to the standard, but this isn't one of them.

Gergo Barany

unread,
Jan 19, 2001, 1:29:19 PM1/19/01
to
Craig Barkhouse <cr...@wanware.com> wrote:
> "Joona I Palaste" <pal...@cc.helsinki.fi> wrote in message
> news:949o09$171$2...@oravannahka.helsinki.fi...
> > brij...@my-deja.com scribbled the following:
> > > a[i++] = a[i++] + 10;
> >
> > [It invokes undefined behavior.]

>
> Um, no, you got carred away here. If the statement were to invoke undefined
> behaviour, you could justifiably jest that these things might happen. That
> is not the case here. Section 6.5.2.4 of the draft standard make it clear
> that "i++" evaluates to i, with a side effect of incrementing the value of i
> by one at some indeterminate time between the previous sequence point and
> the next sequence point. The only thing that is undefined is *exactly when*
> i gets incremented. If incrementing a variable could have side effects like
> the ones you list, then it's safe to say that the behaviour of any program
> is undefined.

Would you care to interpret the following for us?

6.5 Expressions

[#2] Between the previous and next sequence point an 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.60) *

60)This paragraph renders undefined statement expressions
such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;

Gergo

--
Life is like an analogy.

Dan Pop

unread,
Jan 19, 2001, 1:16:59 PM1/19/01
to
In <949mnk$hib$1...@nnrp1.deja.com> brij...@my-deja.com writes:

If you're writing a C compiler, your reference should be one of the
C standards (C89 or C99) and NOT K&R.

The C standard clearly explains that *any* behaviour is correct for such
code, because it invokes undefined behaviour.

Dan
--
Dan Pop
CERN, IT Division
Email: Dan...@cern.ch
Mail: CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland

Richard Heathfield

unread,
Jan 19, 2001, 3:06:32 PM1/19/01
to
Craig Barkhouse wrote:
>
<snip>

>
> > The problem is: i is incremented TWICE without intervening sequence point.
>
> I realize that. I'm agreeing that the incrementations could be done at any
> time between the sequence points (re-read my paragraph). What I'm saying
> is: The uncertainty in order of events doesn't mean that *anything* could
> happen. There are only a few possible outcomes for the statement in
> question. Some array element (either a[0] or a[1]) will get assigned a
> value equal to 10 plus some other array element (either 11 or 12), depending
> on what order the implementation chooses. So any of these values could
> result: {11,2,3,4} {12,2,3,4} {1,11,3,4} {1,12,3,4}. I don't see how any
> other behaviour is conformant. There are operations that result in
> "undefined behaviour" according to the standard, but this isn't one of them.

Yes, it is.

ISO/IEC 9899:1999 6.5 #2 says:

"Between the previous and next sequence point an object shall have its
stored value
modified at most once by the evaluation of an expression. Furthermore,
the prior value

shall be read only to determine the value to be stored.70)"

70) says:

70) This paragraph renders undefined statement expressions such as


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

while allowing

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

Now, whilst I agree that the footnote is non-normative, I venture to
suggest that if you were to ask any voting member of the ISO C committee
whether this code invoked undefined behaviour, you would get an
affirmative response. Why don't you try it?


--
Richard Heathfield
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

willem veenhoven

unread,
Jan 19, 2001, 3:18:52 PM1/19/01
to
brij...@my-deja.com wrote:
>
> a[i++] = a[i++] + 10;
>
> All the compilers i tried it on (gcc, VC, Borland C) incremented i
> after the whole statement (...) I am writing a compiler for C and

> want to know which of the above behaviour is expected from a
> post-increment operator.

I know all guru's in clc will agree that this is a typical case of
undefined behaviour. But you would do me and maybe also some others a
big favour if you do not flip a coin on this. My compiler does not show
any signs of undefined behaviour. It always produces the same results,
and I would like our relation to continue that way.

It seems to me that the compilers you mentioned cover most of the
C-world, so please accept whatever choice they made. If your compiler
will be popular some day, that might save us a lot of work to debug
undefined behaviour of our real world programs ;)

willem

Kaz Kylheku

unread,
Jan 19, 2001, 3:14:57 PM1/19/01
to

The behavior is undefined. Thus, as a compiler writer, you do not have
to worry about it at all. You are free to assume that 1) no expression
will modify the same object twice between sequence points, and that 2)
no expression will access a modified object in any path that does not
lead to the computation of the new value being stored. If a program
does this, it is screwed and it's not your fault, it's the clueless or
careless programmer's fault.

If you want to handle undefined behavior, the absolute best way is to
detect it, produce a diagnostic and terminate the program. If you
silently provide some result, you are not ``handling'' the incorrect
construct in any sense of the word other than ``taking the
punishment with grace''. :)

However, not all undefined behavior is easily detected. Undefined
behavior arising out of ambigous expressions falls into this category.
Consider something like:

int increment_and_add(int *p, int *q)
{
return *q++ + *p++;
}

The behavior of this is well defined if p and q point to different
objects, otherwise it is undefined. So, in general, only an expensive
run time check can detect whether or not the behavior is correct.

Craig Barkhouse

unread,
Jan 19, 2001, 3:39:19 PM1/19/01
to
> Would you care to interpret the following for us?
>
> 6.5 Expressions
>
> [#2] Between the previous and next sequence point an 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.60) *
>
> 60)This paragraph renders undefined statement expressions
> such as
> i = ++i + 1;
> a[i++] = i;
> while allowing
> i = i + 1;
> a[i] = i;

I believe this footnote is flawed, and should actually say "unspecified
behaviour" rather than undefined. Here is the definition of unspecified
behaviour form the draft standard (it might be slightly different in the
actual standard):

3.19
[#1] unspecified behavior
behavior where this International Standard provides two or
more possibilities and imposes no 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.

It is acknowledged that "i = i + 1" is well-defined. Consider "i = ++i + 1"
from footnote 60). The RHS evaluates to two greater than the original value
of i, which gets assigned to i. At some point either before or after this
assignment, i gets incremented. If incremented before the assignment, then
i will end up being two greater than it was originally, effectively ignoring
the assignment; if after, then i will end up being either three greater than
it was originally. The implementation has a limited choice, that's all,
just as it has a choice as to what order to evaluation arguments to a
function, as in the my example #2. Thus, I believe the original the
statement mentioned in this thread invokes "unspecified behaviour", not
"undefined behaviour", footnote 60) notwithstanding.

Chris Torek

unread,
Jan 19, 2001, 3:46:19 PM1/19/01
to
In article <XB1a6.34817$7.12...@quark.idirect.com>

Craig Barkhouse <cr...@wanware.com> writes:
>It is acknowledged that "i = i + 1" is well-defined. Consider "i = ++i + 1"
>from footnote 60). The RHS evaluates to two greater than the original value
>of i, which gets assigned to i. At some point either before or after this
>assignment, i gets incremented.

You omit the third possibility: i gets incremented at the *same time*
as the assignment.

There are computers that can in fact do this (multiple functional
units). This kind of operation is typically labeled "do not do
this because the result is unpredictable". It invariably turns out
that one or the other operations "happens first" when you look at
the result, but the one that "happens first" is sometimes indeed
unpredictable, as it depends on whether an interrupt occurs, etc.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.

Kaz Kylheku

unread,
Jan 19, 2001, 4:00:40 PM1/19/01
to
On Fri, 19 Jan 2001 16:55:50 GMT, Craig Barkhouse <cr...@wanware.com> wrote:
>Um, no, you got carred away here. If the statement were to invoke undefined
>behaviour, you could justifiably jest that these things might happen. That
>is not the case here. Section 6.5.2.4 of the draft standard make it clear
>that "i++" evaluates to i, with a side effect of incrementing the value of i
>by one at some indeterminate time between the previous sequence point and
>the next sequence point. The only thing that is undefined is *exactly when*
>i gets incremented.

When an incorrect program introduces an evaluation ambiguity that
depends on the timing of this increment, the whole program's behavior
becomes undefined. It's valid for an implementation to detect it and
bring up a game of Tetris. It's not the case that the implementation
must choose from a finite set of correct possibilites---that happens
with unspecified and implementation-defined behaviors. Undefined means
behavior means anything can happen, not limited to any enumerable
choices.

Gergo Barany

unread,
Jan 19, 2001, 4:21:16 PM1/19/01
to
[Sorry for the long quote, but I felt all of it was needed for
context.]

This argument doesn't take all the facts into consideration. The
footnote merely says that the paragraph at the top applies to
statements of the form "i = i++" and the like. That paragraph uses
the word "shall" twice outside of constraints. Therefore, this
applies:

4. Conformance

[#2] If a ``shall'' or ``shall not'' requirement that
appears outside of a constraint is violated, the behavior is
undefined. Undefined behavior is otherwise indicated in
this International Standard by the words ``undefined
behavior'' or by the omission of any explicit definition of
behavior. There is no difference in emphasis among these
three; they all describe ``behavior that is undefined''.

The UB comes from the "shall"s, not from the footnote or whether or
not there is a finite number of possibilities to interpret the
statement in question.

Gergo

--
To be successful, a woman has to be much better at her job than a man.
-- Golda Meir

Craig Barkhouse

unread,
Jan 19, 2001, 4:28:14 PM1/19/01
to
Gergo, Kaz, and others,

You have all been very convincing and yet civilized at the same time. I
accept that my interpretation of the standard was wrong. I had thought that
the issue was one of order of evaluation, but the more relevant issue was
modifying a variable more than once between sequence points. I was probably
trying to argue something that has been hased out many times by C.L.C.
regulars, which is a fruitless enterprise. :) Thanks for the discussion.
I will bow out now. "i = i++" should indeed cause demons to fly out of the
floppy drive.

Kelsey Bjarnason

unread,
Jan 19, 2001, 4:35:23 PM1/19/01
to
[snips]

"Craig Barkhouse" <cr...@wanware.com> wrote in message
news:fY_96.34592$7.12...@quark.idirect.com...


> > The problem is: i is incremented TWICE without intervening sequence
point.
>
> I realize that.

Keep that in mind for a moment...

> I'm agreeing that the incrementations could be done at any
> time between the sequence points (re-read my paragraph). What I'm saying
> is: The uncertainty in order of events doesn't mean that *anything* could
> happen. There are only a few possible outcomes for the statement in
> question. Some array element (either a[0] or a[1]) will get assigned a
> value equal to 10 plus some other array element (either 11 or 12),
depending
> on what order the implementation chooses. So any of these values could
> result: {11,2,3,4} {12,2,3,4} {1,11,3,4} {1,12,3,4}. I don't see how any
> other behaviour is conformant. There are operations that result in
> "undefined behaviour" according to the standard, but this isn't one of
them.

From WG14/N869 Committee Draft -- January 18, 1999


6.5 Expressions
[#2] Between the previous and next sequence point an 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.

i is an object; i's value is modified more than once between sequence
points; which suggests to me that, in fact, the code is performing a
sequence of operations in direct contravention of the standard. As a
result, it's operation is, in fact, undefined. So what does undefined
behaviour leave us with?

3.18
[#1] undefined behavior
behavior, upon use of a nonportable or erroneous program
construct, of erroneous data, or of indeterminately valued
objects, for which this International Standard imposes no
requirements

Note that last bit, "No requirements." The implementation is completely
within its rights to teleport you to Neptune without a pressure suit if it
a) feels like it and b) can figure out how to do it. That most
implementations don't do this indicates nothing more than a lack of
imagination on the part of the compiler developers.


Kaz Kylheku

unread,
Jan 19, 2001, 4:40:58 PM1/19/01
to
On Fri, 19 Jan 2001 21:28:14 GMT, Craig Barkhouse <cr...@wanware.com> wrote:
>Gergo, Kaz, and others,
>
>You have all been very convincing and yet civilized at the same time. I
>accept that my interpretation of the standard was wrong. I had thought that
>the issue was one of order of evaluation, but the more relevant issue was
>modifying a variable more than once between sequence points.

This issue *is* order of evaluation. Normally, the permisiveness in
the order of evaluation does not cause problems; but when objects are
modified as part of evaluation, then ambiguities in the evaluation
order arise.

Modifying an object more than once is one possible mistake. There is
another mistake that can occur even of an object is modified just once,
exemplified by:

j = i + i++;

Here the value of the modified object i is observed through an
independent expression (namely the left operand of the + operator).
The expression is independent because it does not contribute to the
computation of the new value of i. Contrast that with

i = i + 1;

where access to i on the right must take place before the new value
stored in i is computed. The dataflow dependency resolves the
ambiguity.

C's permisiveness in order of evaluation can cause unexpected results
even in circumstances when the behavior is well defined. Consider:

a() + b() + c();

There are six possible orders in which the functions a, b and c can be
called. This is unspecified behavior: the implementation has six
choices and can make any one of them without documenting how the choice
is made. If the functions have side effects, the behavior of the
program can be affected by the choice.

Steven Huang

unread,
Jan 19, 2001, 4:57:00 PM1/19/01
to
In article <94a925$baa$1...@elf.bsdi.com>,
to...@elf.bsdi.com (Chris Torek) wrote:
[...]

> You omit the third possibility: i gets incremented at the *same
> time* as the assignment.
[...]

Could there be a fourth possibility? Since sequence points are a
source code concept and not an object code concept, we wouldn't
in general find specific places in a generated assembly listing
where all side effects of one statement complete, and none of the
next statement has started. This, of course, allows optimizing
compilers to interleave assembly instructions of nearby statements
for optimal CPU scheduling.

The question is, at which point can the compiler consider that a
certain register is free for use by the next statement? If the
register holds a value that is modified twice, can it "free" the
register after the first modification? For example, given:

i = i++;
j = 3;

is the following possible?

LOAD r1, [i] ; i = i;
STORE [i], r1 ; i = i;
; at this point, the first modification i = i
; is complete, so r1 is freed up
MOV r1, 3 ; first half of j = 3
ADD r1, 1 ; i++
STORE [i], r1 ; i++
; at this point, the second modification
; completes
STORE [j], r1 ; second half of j = 3

I think it is, because since any subsequent modification of i
results in undefined behavior, the compiler should be able to
conclude that i is modified at most once, and the corresponding
register is free for other uses as soon as i is modified.
IOW, why should we require a compiler keep track of where in the
object code i is *last* modified, rather than just the first
time?

If so, i would eventually always become 4 (which is in general
not any of the possibilities Craig expected), and worse, j
would be also 4.

Note: this post is a question more than it is an assertion.

Robert Stankowic

unread,
Jan 20, 2001, 12:07:17 AM1/20/01
to
Craig Barkhouse schrieb:

No, the standard explicitely says:
From J.2 Undefined behaviour:

— Between two sequence points, an object is modified more than once,
or is modified
and the prior value is accessed other than to determine the value to
be stored (6.5).

So I'd vote for undefined ;-)

--
Robert Stankowic
pcdo...@netway.at
"The regular early morning yell of horror" - Douglas Adams

Keith Thompson

unread,
Jan 20, 2001, 1:17:05 AM1/20/01
to
willem veenhoven <wil...@veenhoven.com> writes:
> brij...@my-deja.com wrote:
> >
> > a[i++] = a[i++] + 10;
> >
> > All the compilers i tried it on (gcc, VC, Borland C) incremented i
> > after the whole statement (...) I am writing a compiler for C and
> > want to know which of the above behaviour is expected from a
> > post-increment operator.
>
> I know all guru's in clc will agree that this is a typical case of
> undefined behaviour. But you would do me and maybe also some others a
> big favour if you do not flip a coin on this. My compiler does not show
> any signs of undefined behaviour. It always produces the same results,
> and I would like our relation to continue that way.

Certainly your compiler shows signs of undefined behavior. Remember,
the consequences of undefined behavior can range from consistently
doing exactly what you expect, to behaving randomly, to consistently
making demons fly out your nose.

A compiler is allowed to behave consistently in the presence of
undefined behavior, but it's not doing you or anyone else any real
favors by doing so. The biggest favor your compiler could do for you
is to complain as early as possible about the error in your program.
In many cases, though, this is difficult or impossible -- which is why
the standard lets compilers get away with not complaining about it.

(For example, consider the above expression with the first i replaced
with (*ptr1) and the second replaced with (*ptr2). The revised
expression invokes undefined behavior only if ptr1 and ptr2 happen to
point to the same object.)

> It seems to me that the compilers you mentioned cover most of the
> C-world, so please accept whatever choice they made. If your compiler
> will be popular some day, that might save us a lot of work to debug
> undefined behaviour of our real world programs ;)

Behaving consistently in the presence of undefined behavior makes it
more difficult to debug. It only saves you work in the sense that it
keeps you from knowing that you need to do it.

--
Keith Thompson (The_Other_Keith) k...@cts.com <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
MAKE MONEY FAST!! DON'T FEED IT!!

Richard Heathfield

unread,
Jan 20, 2001, 4:20:15 AM1/20/01
to
Craig Barkhouse wrote:
>
> Gergo, Kaz, and others,
>
> "i = i++" should indeed cause demons to fly out of the
> floppy drive.

Actually, you're /still/ wrong. "i = i++" is a string literal. No
undefined behaviour there. ;-)

On a slightly (but not much) more serious note, i = i++ /may/ cause
demons to fly out of the floppy drive, but C does not /require/ that it
does. i = i++ might have a more subtle effect, such as changing a
particular leaf on a particular tree deep in the Amazon rainforest from
one shade of green to a very slightly darker shade. Or it may force a
butterfly to flap its wings (the so called "i = i++ effect", well known
to chaoticians and lepidopterists, and most distressing for the
butterfly).

Richard Heathfield

unread,
Jan 20, 2001, 4:23:08 AM1/20/01
to
Robert Stankowic wrote:
>
<snip>

>
> No, the standard explicitely says:
> From J.2 Undefined behaviour:

Please remember that J.2 is a non-normative Annex, for information only.
It is therefore, IMHO, suitable for convincing yourself but not
sufficient for persuading others.

<snip>

Chris Torek

unread,
Jan 20, 2001, 5:37:35 AM1/20/01
to
[I noted]
>> You omit [a] third possibility: i gets incremented at the *same
>> time* as the assignment.

In article <94ad78$7ka$1...@nnrp1.deja.com>


Steven Huang <steven...@iname.com> writes:
>Could there be a fourth possibility? Since sequence points are a
>source code concept and not an object code concept, we wouldn't
>in general find specific places in a generated assembly listing
>where all side effects of one statement complete, and none of the
>next statement has started. This, of course, allows optimizing
>compilers to interleave assembly instructions of nearby statements
>for optimal CPU scheduling.
>
>The question is, at which point can the compiler consider that a
>certain register is free for use by the next statement? If the
>register holds a value that is modified twice, can it "free" the
>register after the first modification?

[example that produces "interesting" result snipped]

This seems plausible, and certainly does not violate any ANSI-C
rules.

If I were writing a compiler myself, and doing something along
these lines, I would probably just use an "increment the register"
flag. Given your example (snipped) this compiler should be able
to produce a warning, but with more complex examples, you would
get the same weird result and no warning.

willem veenhoven

unread,
Jan 20, 2001, 6:16:55 AM1/20/01
to
Keith Thompson wrote:
>
> willem veenhoven <wil...@veenhoven.com> writes:
> > brij...@my-deja.com wrote:
> > >
> > > a[i++] = a[i++] + 10;
> > >
> > I know all gurus in clc will agree that this is a typical case of

> > undefined behaviour. But you would do me and maybe also some others
> > a big favour if you do not flip a coin on this. My compiler does
> > not show any signs of undefined behaviour. It always produces the
> > same results, and I would like our relation to continue that way.
>
> Certainly your compiler shows signs of undefined behavior. Remember,
> the consequences of undefined behavior can range from consistently
> doing exactly what you expect, to behaving randomly, to consistently
> making demons fly out your nose. ...

This is what I expect from a compiler based on my own sense for logic:

int i=0, a[] = {1,2,3};

a[i++] = a[i++] + 10; => i=2, a[] = {11,2,3}
a[++i] = a[++i] + 10; => i=2, a[] = {1,2,13}
a[++i] = a[i++] + 10; => i=2, a[] = {1,12,3}
a[i++] = a[++i] + 10; => i=2, a[] = {1,12,3}

... and that is exactly what I get. So I am very glad my compiler and I
share the same feeling about handling 'undefined behaviour'.

I never noticed my compiler to behave 'randomly'. It may not always do
exactly what I expect, but knowing the results of an operation, it does
at least always behave consistently. Can you give me an example of
random behaviour in this context for one of the compilers listed by the
OP (gcc, VC, BCC)?

willem

Richard Heathfield

unread,
Jan 20, 2001, 8:06:29 AM1/20/01
to
willem veenhoven wrote:
>
<snip>

>
> ... and that is exactly what I get. So I am very glad my compiler and I
> share the same feeling about handling 'undefined behaviour'.

What if your implementation flips a random bit in a random file
somewhere on your network, once for every 1963rd run of a program in
which the construct i = i++ (or whatever) is used?

This behaviour would be entirely in accordance with the Standard. How do
you /know/ your implementation doesn't do this?

>
> I never noticed my compiler to behave 'randomly'. It may not always do
> exactly what I expect, but knowing the results of an operation, it does
> at least always behave consistently. Can you give me an example of
> random behaviour in this context for one of the compilers listed by the
> OP (gcc, VC, BCC)?

Don't make the mistake of thinking that the compiler's behaviour defines
the language. It doesn't.

Robert Stankowic

unread,
Jan 20, 2001, 8:56:22 AM1/20/01
to
Richard Heathfield schrieb:

>
> Robert Stankowic wrote:
> >
> <snip>
> >
> > No, the standard explicitely says:
> > From J.2 Undefined behaviour:
>
> Please remember that J.2 is a non-normative Annex, for information only.
> It is therefore, IMHO, suitable for convincing yourself but not
> sufficient for persuading others.
>

"To get the best out of that book I strongly recommend to read it"
(I am quoting you I think).
You probably should have added "carefully" :-)
Sorry about my mistake

Kaz Kylheku

unread,
Jan 20, 2001, 2:18:23 PM1/20/01
to
On Fri, 19 Jan 2001 21:18:52 +0100, willem veenhoven
<wil...@veenhoven.com> wrote:
>big favour if you do not flip a coin on this. My compiler does not show
>any signs of undefined behaviour.

It's not possible to show signs of undefined behavior, because
undefined behavior can be any behavior whatsoever, not some specific
class of behaviors. Undefined behavior simply means that whatever
behavior you are seeing is not required. From merely observing a
behavior, it cannot be inferred that it is not required!

Chris Torek

unread,
Jan 20, 2001, 2:47:50 PM1/20/01
to
>On Fri, 19 Jan 2001 21:18:52 +0100, willem veenhoven
><wil...@veenhoven.com> wrote:
>>big favour if you do not flip a coin on this. My compiler does not show
>>any signs of undefined behaviour.

In article <slrn96jpf...@ashi.FootPrints.net>,


Kaz Kylheku <k...@ashi.footprints.net> wrote:
>It's not possible to show signs of undefined behavior, because
>undefined behavior can be any behavior whatsoever, not some specific
>class of behaviors. Undefined behavior simply means that whatever
>behavior you are seeing is not required. From merely observing a
>behavior, it cannot be inferred that it is not required!

Right -- willem veenhoven is confusing "undefined behavior"
with "unpredictable behavior".

If the behavior is undefined, all that really means is that the
Standard says "anything can happen". If the compiler and hardware
choose some particular, consistent behavior, whether deliberately
or accidentally, you can subsequently observe that behavior all
you want.

Now, one argument one can make is: "I observed this behavior, and
I have tested several thousand compilers and systems and have
*always* observed this particular behavior. Moreover, I find this
particular behavior (useful, aethestically pleasing, whatever).
I therefore request that C0x define the behavior in the way that
it actually works..." If the C0x committee listen to you, it
might even become defined behavior.

But it might not -- and in the meanwhile it is still undefined.
Use it at your own risk.

Kaz Kylheku

unread,
Jan 20, 2001, 2:47:07 PM1/20/01
to
On Sat, 20 Jan 2001 12:16:55 +0100, willem veenhoven
<wil...@veenhoven.com> wrote:
>
>This is what I expect from a compiler based on my own sense for logic:

You mean, based on your assumptions. Logic is simply the process by
which we proceed from one statement to another, including from false
assumptions to ridiculous conclusions.

> int i=0, a[] = {1,2,3};
>
> a[i++] = a[i++] + 10; => i=2, a[] = {11,2,3}
> a[++i] = a[++i] + 10; => i=2, a[] = {1,2,13}
> a[++i] = a[i++] + 10; => i=2, a[] = {1,12,3}
> a[i++] = a[++i] + 10; => i=2, a[] = {1,12,3}
>
>... and that is exactly what I get. So I am very glad my compiler and I
>share the same feeling about handling 'undefined behaviour'.

Your compiler doesn't have feeling. Besides, you said that you have a
sense for logic, not a feeling. This means that you must have some
formal idea about how your compiler evaluates these expressions---some
set of rules that you can write down and say, this is how my compiler
does it for every possible expression. Moreover, you must have some
document written by the makers of your compiler which confirms the
validity of your model of what it is doing, along with some assurance
that future versions of the compiler will use the same scheme.

Without that, you are just bullshitting yourself.

>I never noticed my compiler to behave 'randomly'. It may not always do

Undefined behavior doesn't mean random behavior. It simply means
behavior that is not required. It's inherently nonportable and
unsafe, regardless of the consistency of results that it produces on
one compiler.

>exactly what I expect, but knowing the results of an operation, it does
>at least always behave consistently.

Have you tried different optimization settings? One compiler is
typically many compilers rolled into one; each setting which affects
code generation potentially gives rise to a different flavor of the
compiler. Moreover, what if a new release of the compiler comes out and
you want to upgrade due to bugfixes and other improvements? Are you
sure that the new version will have the same behaviors?

Also, don't forget: even if the code will only ever target only one
version of one compiler operated with invariant settings, there are
always other programmers who read the code and interpret its meaning.
The language is not interpreted by machines alone, but also by humans!
If another programmer comes across your ambiguous expression, how will
he or she know what translation you intended? Without knowing the
*intent* of the code, it's impossible to verify whether that one and
only compiler is translating it according to that intent. Right now,
you know the intent because you wrote it. That programmer who doesn't
understand the intent could be yourself, in six months.

Lastly, consider that predictions like ``this code only needs to run on
this compiler'' can be self-fulfilling. By using non-portable
constructs, you may in fact ensure that nobody can get it working on
another compiler, even if the need does arise.

Dan Pop

unread,
Jan 20, 2001, 2:59:39 PM1/20/01
to

>Robert Stankowic wrote:
>>
><snip>
>>
>> No, the standard explicitely says:
>> From J.2 Undefined behaviour:
>
>Please remember that J.2 is a non-normative Annex, for information only.
>It is therefore, IMHO, suitable for convincing yourself but not
>sufficient for persuading others.

Not so. It may be an informative appendix, but it provides pointers to
the normative part of the standard for each instance of undefined
behaviour listed. Looks quite convincing to me :-)

Keith Thompson

unread,
Jan 20, 2001, 3:20:20 PM1/20/01
to
willem veenhoven <wil...@veenhoven.com> writes:
[...]

> This is what I expect from a compiler based on my own sense for logic:
>
> int i=0, a[] = {1,2,3};
>
> a[i++] = a[i++] + 10; => i=2, a[] = {11,2,3}
> a[++i] = a[++i] + 10; => i=2, a[] = {1,2,13}
> a[++i] = a[i++] + 10; => i=2, a[] = {1,12,3}
> a[i++] = a[++i] + 10; => i=2, a[] = {1,12,3}
>
> ... and that is exactly what I get. So I am very glad my compiler and I
> share the same feeling about handling 'undefined behaviour'.
>
> I never noticed my compiler to behave 'randomly'. It may not always do
> exactly what I expect, but knowing the results of an operation, it does
> at least always behave consistently. Can you give me an example of
> random behaviour in this context for one of the compilers listed by the
> OP (gcc, VC, BCC)?

gcc version 4.17, released in 2023, sets i to 1 and a[] to {11,12,3}.
This is a side effect of some extremely clever optimizations it
performs for Inanium VI processors, taking advantage of the
thiotimoline-based cache.

Yes, of course I'm making this up, but there's nothing in the standard
that prevents it. If you write code that depends on your
interpretation, or even experience, of undefined behavior, it's *very*
likely to break when a new compiler comes out, or when you compile for
a different target machine, or use a different set of optimization
switches. When you submit your bug report, the compiler vendor will
rightly tell you to fix your code.

If there were some advantage to be gained by modifying a variable
twice in a single expression, I could understand your position -- but
there isn't. If you have something like


a[i++] = a[i++] + 10;

in your code, just change it to
a[i] += 10;
i += 2;
It's clearer, it's unambiguous, it works, and it won't break when you
port it to a different compiler.

Richard Heathfield

unread,
Jan 20, 2001, 3:20:49 PM1/20/01
to
Dan Pop wrote:
>
> In <3A6958FC...@eton.powernet.co.uk> Richard Heathfield <bin...@eton.powernet.co.uk> writes:
>
> >Robert Stankowic wrote:
> >>
> ><snip>
> >>
> >> No, the standard explicitely says:
> >> From J.2 Undefined behaviour:
> >
> >Please remember that J.2 is a non-normative Annex, for information only.
> >It is therefore, IMHO, suitable for convincing yourself but not
> >sufficient for persuading others.
>
> Not so. It may be an informative appendix, but it provides pointers to
> the normative part of the standard for each instance of undefined
> behaviour listed. Looks quite convincing to me :-)

In the general case, annexes are informative, not normative (exceptions:
D and F). It is of course true that they might point you back into the
normative standard, in which case they are useful as indices to
persuasion. Dan is convinced already, so you can show him a J.2 ref and
sit back cheerfully. If you were trying to persuade someone fussy and
pedantic and pernickety (i.e. someone totally unlike Dan Pop), however,
they could argue that annexes are not (except for D and F) normative,
and so you'd have to snap Dan's pointers yourself.

Scott Fluhrer

unread,
Jan 20, 2001, 11:44:07 AM1/20/01
to

Kaz Kylheku <k...@ashi.footprints.net> wrote in message
news:slrn96h8d...@ashi.FootPrints.net...

>
> However, not all undefined behavior is easily detected. Undefined
> behavior arising out of ambigous expressions falls into this category.
> Consider something like:
>
> int increment_and_add(int *p, int *q)
> {
> return *q++ + *p++;
> }
>
> The behavior of this is well defined if p and q point to different
> objects, otherwise it is undefined.
Actually, that's well defined. I suspect you meant something like:

int increment_and_add(int *p, int *q)
{

return ++*p + ++*q;
}

"Look! A nit! Pick it! Pick it!"

--
poncho

Gordon Burditt

unread,
Jan 20, 2001, 6:52:23 PM1/20/01
to
>***Disclaimer : The example given below is bad programming. However i
>need to handle it...hence the question ***
>
>The question is concerning post-increment in the following context:
>int a[4] ={1,2,3,4};
>int i=0;
>a[i++] = a[i++] + 10;

The correct behavior for a compiler faced with this
code (although this particular behavior is not mandated
by ANSI C, nor is it prohibited) is to generate a
(fatal) ERROR message, and delete the source code.

>All the compilers i tried it on (gcc, VC, Borland C) incremented i

>after the whole statement.

Unfortunately, that isn't wrong.

>So the result was a[]={11,2,3,4}.
>I had expected a[] = {1,11,3,4} from reading K&R

Unfortunately, that isn't wrong either.

>I am writing a compiler for C and want to know which of the above
>behaviour is expected from a post-increment operator.

I want an error.

Gordon L. Burditt

Dan Pop

unread,
Jan 20, 2001, 10:44:54 PM1/20/01
to

Or maybe:

int increment_and_add(int *p, int *q)
{

return (*q)++ + (*p)++;

willem veenhoven

unread,
Jan 21, 2001, 4:25:17 AM1/21/01
to
Keith Thompson wrote:
>
> willem veenhoven <wil...@veenhoven.com> writes:
>
> > a[i++] = a[i++] + 10; => i=2, a[] = {11,2,3}
>
> If there were some advantage to be gained by modifying a variable
> twice in a single expression, I could understand your position -- but
> there isn't. If you have something like
> a[i++] = a[i++] + 10;
> in your code, just change it to
> a[i] += 10;
> i += 2;
> It's clearer, it's unambiguous, it works, and it won't break when you
> port it to a different compiler.

Thanks for the lesson Keith. I fully agree with your suggestions to
improve my programming style, though I can't remember the last time I
had written such a statement in any of my programs.

However, it might help to remember that the OP is writing a compiler(!)
and that he asked this group's opinion on a[i++] = a[i++] + 10.

How will your answer help him? Should he add another precompiler stage
for rewriting source?

willem

willem veenhoven

unread,
Jan 21, 2001, 5:06:53 AM1/21/01
to
Chris Torek wrote:

>
> >willem veenhoven wrote:
> >>My compiler does not show any signs of undefined behaviour.
>
> Kaz Kylheku <k...@ashi.footprints.net> wrote:
> >It's not possible to show signs of undefined behavior, because
> >undefined behavior can be any behavior whatsoever, not some specific
> >class of behaviors. Undefined behavior simply means that whatever
> >behavior you are seeing is not required. From merely observing a
> >behavior, it cannot be inferred that it is not required!
>
> Right -- willem veenhoven is confusing "undefined behavior"
> with "unpredictable behavior".

I think someone upthread oversnipped. I did not introduce 'random
behaviour' into the discussion. I now know - you explained that to me
yourself before -, that undefined behaviour refers to the implementor's
freedom to take whatever action he likes, whithout being penalized with
not being compliant anymore.

> If the behavior is undefined, all that really means is that the
> Standard says "anything can happen". If the compiler and hardware
> choose some particular, consistent behavior, whether deliberately
> or accidentally, you can subsequently observe that behavior all
> you want.

However, the OP is writing a compiler, so he is free to implement any
action on ridiculous statements like a[i++] = a[i++] + 10.
After he made his choice, the behaviour stops being undefined, simply
because he defined it. That is really all I ment to say stating 'my
compiler does not show any signs of undefined behaviour'.
It's fun to see how my 10 words have been stretched to a full dialogue
about behaviour, but thus far the OP did not get any answer on his
question ...

> Now, one argument one can make is: "I observed this behavior, and
> I have tested several thousand compilers and systems and have
> *always* observed this particular behavior. Moreover, I find this
> particular behavior (useful, aethestically pleasing, whatever).
> I therefore request that C0x define the behavior in the way that
> it actually works..." If the C0x committee listen to you, it
> might even become defined behavior.

OP tested several compilers from major vendors and noticed that they in
fact all increment 'i' after the whole expression. I told him that it
would probably not be unwise to implement the same behaviour in his
compiler, to fill this void left by the people who wrote the code.

It doesn't sound that unlogical to me, that the code committee might
adopt the choice of major companies in the 2009 release, which will be
published in 2012 of course. That is how it works with these kind of
committees, isn't it?

willem (testing his Forester in the snow today :)

willem veenhoven

unread,
Jan 21, 2001, 5:54:10 AM1/21/01
to
Richard Heathfield wrote:
>
> willem veenhoven wrote:
> >
> <snip>

> >
> > I never noticed my compiler to behave 'randomly'. It may not
> > always do exactly what I expect, but knowing the results of an
> > operation, it does at least always behave consistently.
> > Can you give me an example of random behaviour in this context
> > for one of the compilers listed by the OP (gcc, VC, BCC)?
>
> Don't make the mistake of thinking that the compiler's behaviour
> defines the language. It doesn't.

Though I must admit that I don't have any experience with ISO language
committees, I do have a lot of experience on how things work with
building codes. Because I can't see any reason why C-engineers would
behave totally different from building engineers, I think that your
assumption doesn't hold. In practice it is often the case that the code
just follows the implementations ...

willem

Ian Woods

unread,
Jan 21, 2001, 7:17:26 AM1/21/01
to
wil...@veenhoven.com (willem veenhoven) wrote in
<3A6ABFD2...@veenhoven.com>:


And in buildings the same problems occur of 'undefined behaviour'. One
building technique that was 'implemented' was to build a number of vertical
steel struts as high as your building would go. At the top of each would be
a winch-like mechanism. You then proceed to make floors, out of concrete,
at the bottom and hoist them up. Once they're in the correct place you put
a locking mechanism in to stop them falling down again. The really cool
thing about this is that it allowed you to add higher up floors whilst you
wer actually decorating and putting walls into the lower floors! Cool...
parallel building!

There's only one problem. When the engineers who designed the winch system
did it they explicictely stated the loading and the kind of forces these
things could support. In terms of weight it was huge! In terms of 'side-
ways' stess it was okay or buildings up to about fifteen floors if there
was no wind. One day, some builders ('implementors') found this out the
painful and expensive and lethal way. They were hoisting up a floor to
where it needed to be (about floor 18 or something)... the locking
mechanism on the winch failed because the wind blew and the whole floor
came down... landed on the next one... and the same thing happened. In the
end.. all the floors were back at the boottom, all kind of broken into
tiny pieces. Somewhere in between were the couple of hundred builders who
were now about 2 inches high and very red and leaking or broken into tiny
pieces themselves.

The ISO C standard says what you can and can't do in ISO C. If you do
something outside the scope of ISO C you invite the possibility of nasty
things occuring because you cannot gaurentee that they won't occur (unless
the implementation explicitely defines in it's documentation, but thne
you're no longer portable).

The fact that one implementation at one time does one thing for undefined
behaviour doesn't mean that the next build it will do the same (for
instance... it might optimise it differently because you're now asking it
too).

Ian Woods

Chris Torek

unread,
Jan 21, 2001, 9:25:59 AM1/21/01
to
In article <3A6AB4BD...@veenhoven.com>,
willem veenhoven <wil...@veenhoven.com> wrote:
>... However, the OP is writing a compiler, so he is free to implement any

>action on ridiculous statements like a[i++] = a[i++] + 10.
>After he made his choice, the behaviour stops being undefined, simply
>because he defined it.

Well, sort of. In this group the phrase "undefined behavior",
without any additional context, is (or at least should be) taken
to mean "in ISO C". (At one time that would mean ANSI C89 or ISO
C90, now it probably means C99 ... which means that one should say
which one, to avoid even *more* confusion. :-) )

The behavior is perhaps fixed in stone (or at least ones and zeros)
inside that particular compiler, and if it is documented, it could
be "defined behavior for BeebleBrox C on the Zaphod-64". So in that
context, it would be "defined".

>OP tested several compilers from major vendors and noticed that they in
>fact all increment 'i' after the whole expression. I told him that it
>would probably not be unwise to implement the same behaviour in his
>compiler, to fill this void left by the people who wrote the code.

Even better, he could have his compiler notice the more obvious
cases (such as this one) and produce a warning or something.

In general, if I were in that position, for this particular case,
I would try to produce warnings, and in cases for which that is
"too hard" (i.e., whatever code I wrote to detect and warn happens
to miss it), I would just have the compiler "do whatever comes
naturally" at that point. If someone else's non-conformant code
breaks, so be it. It is not as though I could tell what someone
who wrote, say:

a[i] = a[i++] * 2;

meant in the first place. (Did the programmer expect this to double
a[i], then increment i, or did the programmer expect this to set
a[i+1] to twice a[i], and then increment i? I have no idea!)

>It doesn't sound that unlogical to me, that the code committee might
>adopt the choice of major companies in the 2009 release, which will be
>published in 2012 of course. That is how it works with these kind of
>committees, isn't it?

Well, not exactly, no. There has to be some sort of consensus,
amongst the committee members, that it would be useful and prudent
to define some previously-undefined behavior, or tighten down the
specifications on some previously implementation-defined behavior.
The latter, for instance, occurred in C99 with respect to integer
division.

(In C89, n/d is simple when n and d are both positive integers:
you round down. 3/2 is 1, not 2. When one is negative, however,
there are two choices: (-3)/2 can be either -1 or -2. In C99,
the choice has been revoked -- (-3)/2 must be -1. This in turn
means that (-3)%2 must also be -1. The committee reportedly
weighed the cost of forcing such a result vs its advantages, and,
since Fortran has been defined this way, decided that the cost
was minimal compared to the advantage.)

Richard Heathfield

unread,
Jan 21, 2001, 10:14:03 AM1/21/01
to
willem veenhoven wrote:
>
> Richard Heathfield wrote:
> >
<snip>

> >
> > Don't make the mistake of thinking that the compiler's behaviour
> > defines the language. It doesn't.
>
> Though I must admit that I don't have any experience with ISO language
> committees, I do have a lot of experience on how things work with
> building codes. Because I can't see any reason why C-engineers would
> behave totally different from building engineers, I think that your
> assumption doesn't hold. In practice it is often the case that the code
> just follows the implementations ...

Which implementations? What if you don't know in advance which
implementations your code will be running on?

You haven't even the tiniest clue about what "portable" means, have you?

willem veenhoven

unread,
Jan 21, 2001, 10:48:48 AM1/21/01
to
Chris Torek wrote:
>
> willem veenhoven:

>
> >OP tested several compilers from major vendors and noticed that they
> >in fact all increment 'i' after the whole expression. I told him
> >that it would probably not be unwise to implement the same behaviour
> >in his compiler, to fill this void left by the people who wrote the
> >code.
>
> Even better, he could have his compiler notice the more obvious
> cases (such as this one) and produce a warning or something.
>
> In general, if I were in that position, for this particular case,
> I would try to produce warnings, and in cases for which that is
> "too hard" (i.e., whatever code I wrote to detect and warn happens
> to miss it), I would just have the compiler "do whatever comes
> naturally" at that point. If someone else's non-conformant code
> breaks, so be it. It is not as though I could tell what someone
> who wrote, say:
>
> a[i] = a[i++] * 2;
>
> meant in the first place. (Did the programmer expect this to double
> a[i], then increment i, or did the programmer expect this to set
> a[i+1] to twice a[i], and then increment i? I have no idea!)

The idea of suggesting that compilers should issue a warning or even
signal an error on these kind of operations did cross my mind too,
because even in C99 the effect is undefined - just downloaded an online
copy.

So why do most (if not all) compilers just evaluate and execute the
statement and produce a consistent result without any warning? And why
is that result also the same for gcc, VC and BCC on top of that, which
seems to indicate that there is some consensus on 'whatever becomes
naturally'?

In the case you just presented, my compiler doubled a[i], and then
increment i, which is consistent with the way a[i++] = a[i++] + 10 has
been handled. I predict - I'm not sure though - that other compilers
will do the same. So the (yet unwritten) rule seems to be that i should
be incremented after the assignment. This rule also implies that

a[i++] = a[i++] + a[i++] + a[i++]; (i=0, a[] = {1,2,3})

would set a[0] to 3 and i to 4, which is indeed the case with BCC.

Is that just coincidence, or did a working group of the ISO C committee
discuss the topic, and informally decided this is the way to do it?
I would not be surprised if this happens to be the case ...

willem

willem veenhoven

unread,
Jan 21, 2001, 11:14:07 AM1/21/01
to
Richard Heathfield wrote:
>
> willem veenhoven wrote:
> >
> > Richard Heathfield wrote:
> > >
> <snip>
> > >
> > > Don't make the mistake of thinking that the compiler's behaviour
> > > defines the language. It doesn't.
> >
> > Though I must admit that I don't have any experience with ISO
> > language committees, I do have a lot of experience on how things
> > work with building codes. Because I can't see any reason why
> > C-engineers would behave totally different from building engineers,
> > I think that your assumption doesn't hold. In practice it is often
> > the case that the code just follows the implementations ...
>
> Which implementations? What if you don't know in advance which
> implementations your code will be running on?

Of course I decide in advance which 'implementations' my code will be
running on. Virtual programming may be nice for a hobby, but I can't
build any real world program on that base ...

> You haven't even the tiniest clue about what "portable" means, have
> you?

Thank you.

willem

Chris Torek

unread,
Jan 21, 2001, 11:11:20 AM1/21/01
to
In article <3A6B04E0...@veenhoven.com>

willem veenhoven <wil...@veenhoven.com> writes:
>The idea of suggesting that compilers should issue a warning or even
>signal an error on these kind of operations did cross my mind too,
>because even in C99 the effect is undefined - just downloaded an online
>copy.
>
>So why do most (if not all) compilers just evaluate and execute the
>statement ...

In some cases it is definitely too hard to tell whether there is a
problem. For instance:

a[*p++] = a[*q++] * 2;

If p and q point to two different integers, this code is okay; if the
both point to the same "int i", it is not.

Many compilers seem to leave diagnosing the simple cases (literal
variable "i" repeated) to some kind of "lint" program.

>... and produce a consistent result without any warning?

Consistent with themselves, or with each other (which would include
"with themselves")? I have a counterexample, in a moment, for
"constent with themselves".

>And why is that result also the same for gcc, VC and BCC on top of
>that, which seems to indicate that there is some consensus on 'whatever
>becomes naturally'?

What is "natural" depends on both the compiler and the target
architecture. If you fix the target -- e.g., if you perform all
your tests on one Intel platform -- and if that target encourages
one particular behavior, many (or even all) compilers will end up
doing that.

>... So the (yet unwritten) rule seems to be that i should


>be incremented after the assignment. This rule also implies that
>
> a[i++] = a[i++] + a[i++] + a[i++]; (i=0, a[] = {1,2,3})
>
>would set a[0] to 3 and i to 4, which is indeed the case with BCC.
>
>Is that just coincidence, or did a working group of the ISO C committee
>discuss the topic, and informally decided this is the way to do it?

It is definitely just coincidence. I put the above line into a
program:

% cat foo.c
#include <stdio.h>
int a[] = { 1, 2, 3, 4 };
void f(int);
int main(void) {
f(0);
return 0;
}
void f(int i) {


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

printf("i: %d a: {%d, %d, %d, %d}\n", i, a[0], a[1], a[2], a[3]);
}

and then compiled and ran it:

% cc foo.c
% ./a.out
i: 1 a: {3, 2, 3, 4}
% cc -O foo.c
% ./a.out
i: 4 a: {3, 2, 3, 4}

Same compiler, different optimization levels, different results.

Kaz Kylheku

unread,
Jan 21, 2001, 1:58:47 PM1/21/01
to
On Sun, 21 Jan 2001 11:06:53 +0100, willem veenhoven
<wil...@veenhoven.com> wrote:
>However, the OP is writing a compiler, so he is free to implement any
>action on ridiculous statements like a[i++] = a[i++] + 10.
>After he made his choice, the behaviour stops being undefined, simply
>because he defined it.

That is misleading. The OP having written a compiler does not cause the
text of the standard to magically change. Undefined behavior means
undefined *by the standard*, and it remains undefined regardless of
what implementors do. What you are saying is that there may be a local
definition of behavior that has nothing to do with the language.

Also note that unless the compiler writer produces a detailed document
regarding how ambiguous expressions are treated, the behavior is not a
*documented extension* on that compiler. So there is in fact no local
definition of behavior for the users of that compiler, just something
that works by fluke.

Moreover, one can write a compiler without making an explicit choice on
how to treat these ambiguous statements; you can ignore the issue
completely, ensuring only that correct expressions are handled. So the
act of writing a compiler does not entail a choice of behavior at all.

>It's fun to see how my 10 words have been stretched to a full dialogue
>about behaviour, but thus far the OP did not get any answer on his
>question ...

Actually he did, you just didn't notice.

Richard Heathfield

unread,
Jan 21, 2001, 2:00:50 PM1/21/01
to
willem veenhoven wrote:
>
> Richard Heathfield wrote:
> >
<snip>
> >
> > Which implementations? What if you don't know in advance which
> > implementations your code will be running on?
>
> Of course I decide in advance which 'implementations' my code will be
> running on.

Not everyone has that luxury.

> Virtual programming may be nice for a hobby, but I can't
> build any real world program on that base ...

I can, must, and do.

Kaz Kylheku

unread,
Jan 21, 2001, 2:18:34 PM1/21/01
to
On Sun, 21 Jan 2001 16:48:48 +0100, willem veenhoven
<wil...@veenhoven.com> wrote:
>So why do most (if not all) compilers just evaluate and execute the

A tiny handful of compilers is hardly ``most''.

>statement and produce a consistent result without any warning?

Probably because their implementors decided to collect side effects
into a ``bag'' and then perform them after evaluating the full
expression.

And why
>is that result also the same for gcc, VC and BCC on top of that, which
>seems to indicate that there is some consensus on 'whatever becomes
>naturally'?

There is no such consensus.

>
>In the case you just presented, my compiler doubled a[i], and then
>increment i, which is consistent with the way a[i++] = a[i++] + 10 has
>been handled. I predict - I'm not sure though - that other compilers
>will do the same. So the (yet unwritten) rule seems to be that i should
>be incremented after the assignment. This rule also implies that
>
> a[i++] = a[i++] + a[i++] + a[i++]; (i=0, a[] = {1,2,3})

There is no such unwritten or written rule. Note that the most
straightfoward way of writing a compiler is to use some kind of
syntax-directed translation scheme, in which the code to perform an
expression is emitted as that part of the expression is being
processed, in one pass. So if the compiler is processing (E)++ where
(E) is some expression for which the compiler has emitted code already,
an obvious algorithm is to simply emit code which increments the lvalue
(E), and then designate the result of (E) as the result of (E)++.
This is driven by the parser, when it calls for the reduction of
(E)++. In other words, the most obvious code generation algorithm is
to perform the increment immediately after the prior value is noted.
Implementing such an algorithm means that the compiler does not have to
collect side effects as an inherited attribute; it can emit
the intermediate code as it parses bottom up in one pass.

E.g suppose that (E) was parsed, code-generated, and its result is
stored in an intermediate pseudo-register called r10. Moreover, since
it is an lvalue, its address has been computed into another pseduo
register, call it r9. The compiler can then add the intermediate code:

r11 <- *r9
*r9 <- r11 + 1

and designate r10 as the noted value of the expression. And so the
increments get interspersed with other code as the bottom up
translation scheme is carried out.

>would set a[0] to 3 and i to 4, which is indeed the case with BCC.

Have you varied the optimization settings, or just operated the
compiler in its default mode?

>Is that just coincidence, or did a working group of the ISO C committee
>discuss the topic, and informally decided this is the way to do it?

I'm not aware that the committee has a sub-workgroup, and I'm almost
certain that no such decision took place, because what the committee
did come up with is a formal model of sequence points which is
described in an informative annex of C99. Implementations don't have to
implement that model, but it's very informative about the intended
meaning. The model provides a step by step algorithm for determining
all of the possible orders in which an expression issues accesses to
objects, and rules for determining which orders give rise to undefined
behavior. Since the model covers all possible evaluation orders (other
than parallel ones, but it's easy to extend to cover that) it shows
that ISO C does not favor any particular order; it simply confirms what
every competent C programmer already knows.

>I would not be surprised if this happens to be the case ...

I would be shocked.

Kaz Kylheku

unread,
Jan 21, 2001, 2:34:29 PM1/21/01
to
On Sun, 21 Jan 2001 17:14:07 +0100, willem veenhoven
<wil...@veenhoven.com> wrote:
>> Which implementations? What if you don't know in advance which
>> implementations your code will be running on?
>
>Of course I decide in advance which 'implementations' my code will be
>running on.

That's good for you, but not everyone has that position. For example,
last year I had to port a 100,000 line application to a platform that
wasn't anywhere on the ``corporate radar'' six months before that.
Many of the programmers who worked on it thought about only the one
compiler that was used for the development.

>Virtual programming may be nice for a hobby, but I can't
>build any real world program on that base ...

That's right; you can only write a highly portable program that works
and is delivered on time.

For me, it is better use of my time to use a well-defined language
construct, than to waste time programming by trial-and error, using the
compiler as some kind of experimental apparatus. I leave the
experimentation to the physicists who are trying to discover something
new about the world or confirm a theory; programming languages are man
made entities that are well documented (at least the standardized
ones).

willem veenhoven

unread,
Jan 21, 2001, 4:59:03 PM1/21/01
to
Kaz Kylheku wrote:
>
> For me, it is better use of my time to use a well-defined language
> construct, than to waste time programming by trial-and error, using
> the compiler as some kind of experimental apparatus. I leave the
> experimentation to the physicists who are trying to discover
> something new about the world or confirm a theory; programming
> languages are man made entities that are well documented (at least
> the standardized ones).

well, I think you just pointed out the difference between you and me:
I'm more the experimenting physicist in all aspects of my work. But I
feel quite happy the way I am, so there is no need for any professional
advice on this topic ...

I think we agree on other things you mention in your reply upthread :)

willem

Sergei

unread,
Jan 21, 2001, 8:09:58 PM1/21/01
to
Chris Torek <to...@elf.bsdi.com> wrote in message news:94f1mj$j95$1...@elf.bsdi.com...

>
> In some cases it is definitely too hard to tell whether there is a
> problem. For instance:
>
> a[*p++] = a[*q++] * 2;

In fact it's quite easy!
This is valid code with perfectly defined behaviour.

> If p and q point to two different integers, this code is okay; if the
> both point to the same "int i", it is not.

It is okay whether they point to defferent integers or not.

Sergei

Ben Pfaff

unread,
Jan 21, 2001, 8:29:20 PM1/21/01
to
to...@elf.bsdi.com (Chris Torek) writes:

> In some cases it is definitely too hard to tell whether there is a
> problem. For instance:
>
> a[*p++] = a[*q++] * 2;
>
> If p and q point to two different integers, this code is okay; if the
> both point to the same "int i", it is not.

I think you forgot some parenthesization:

a[(*p)++] = a[(*q)++] * 2;

I don't see any problems in your particular example above; it is
analogous to "*dst++ = *src++;", which works just fine if `dst'
and `src' point to the same place.

Chris Torek

unread,
Jan 22, 2001, 2:06:07 AM1/22/01
to
>Chris Torek <to...@elf.bsdi.com> wrote in message news:94f1mj$j95$1...@elf.bsdi.com...
>> In some cases it is definitely too hard to tell whether there is a
>> problem. For instance:
>> a[*p++] = a[*q++] * 2;

In article <94g220$30vo$1...@gavrilo.mtu.ru>


Sergei <ser...@summertime.mtu-net.ru> writes:
>In fact it's quite easy!
>This is valid code with perfectly defined behaviour.

As Ben Pfaff noted, I forgot to parenthesize -- the line should have
read:

a[(*p)++] = a[(*q)++] * 2;

so that the integers, not the pointers, are post-incremented.

(All I can say is, I was tired when I posted that :-) )

Christian Bau

unread,
Jan 22, 2001, 5:58:45 AM1/22/01
to
In article <3A68A12C...@veenhoven.com>, willem veenhoven
<wil...@veenhoven.com> wrote:

> brij...@my-deja.com wrote:
> >
> > a[i++] = a[i++] + 10;


> >
> > All the compilers i tried it on (gcc, VC, Borland C) incremented i

> > after the whole statement (...) I am writing a compiler for C and


> > want to know which of the above behaviour is expected from a
> > post-increment operator.
>

> I know all guru's in clc will agree that this is a typical case of
> undefined behaviour. But you would do me and maybe also some others a
> big favour if you do not flip a coin on this. My compiler does not show
> any signs of undefined behaviour. It always produces the same results,
> and I would like our relation to continue that way.

Code like that is probably the reason why so much shipping products
contain completely unoptimised code.

Someone writes code invoking undefined behavior, but as long as his
compiler does no optimisations, it happens by coincidence to do what the
programmer expected. Three days before shipping management decides that
the shipping product should use the highest optimisation the compiler can
provide. With optimisation switched on, all these nasty undefined behavior
bugs come crawling out of the woodwork and the program crashes left, right
and center.

So the program ships completely unoptimised. And who gets the blame? The
compiler writer.

I would suggest a compiler option that asks the compiler to produce as
random as possible behavior for all undefined or unspecified behavior that
it encounters.

Christian Bau

unread,
Jan 22, 2001, 6:10:59 AM1/22/01
to
In article <XB1a6.34817$7.12...@quark.idirect.com>, "Craig Barkhouse"
<cr...@wanware.com> wrote:

> I believe this footnote is flawed, and should actually say "unspecified
> behaviour" rather than undefined. Here is the definition of unspecified
> behaviour form the draft standard (it might be slightly different in the
> actual standard):
>
> 3.19
> [#1] unspecified behavior
> behavior where this International Standard provides two or
> more possibilities and imposes no 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.
>
> It is acknowledged that "i = i + 1" is well-defined. Consider "i = ++i + 1"
> from footnote 60). The RHS evaluates to two greater than the original value
> of i, which gets assigned to i. At some point either before or after this
> assignment, i gets incremented. If incremented before the assignment, then
> i will end up being two greater than it was originally, effectively ignoring
> the assignment; if after, then i will end up being either three greater than
> it was originally. The implementation has a limited choice, that's all,
> just as it has a choice as to what order to evaluation arguments to a
> function, as in the my example #2. Thus, I believe the original the
> statement mentioned in this thread invokes "unspecified behaviour", not
> "undefined behaviour", footnote 60) notwithstanding.

First of course the C Standard is right by definition. If it says
something has undefined behavior then it has undefined behavior. So any
further discussion becomes pointless right there.

But to continue this pointless discussion: You make the completely
unwarranted assumption that operations on integers are atomic operations.
But where is that written? Assume you have an eight bit processor with few
registers, and int is sixteen bits. The increment, add and store have to
be done eight bit at a time. Start with i = 254. ++i finds out that the
high byte is unchanged and the low byte becomes 255. i = ++i + 1 stores
high byte = 1, low byte = 0 for a value of 256, and THEN the ++i stores
the 255 into the low byte, giving a result of 511.

If you think there is no such compiler then consider an implementation of
64 bit long long an a 32 bit CPU. Or consider the Merced processor. If you
take correct and good code for j = ++i + 1 on a Merced (which will do two
simultaneous assignments j = i+2 and i=i+1), and then change the assembler
instructions to i = i+2 and i=i+1 simultaneously, the processor will
crash. Kaboom.

Craig Barkhouse

unread,
Jan 22, 2001, 9:02:13 AM1/22/01
to

"Keith Thompson" <k...@cts.com> wrote in message
news:yecitna...@king.cts.com...

> gcc version 4.17, released in 2023, sets i to 1 and a[] to {11,12,3}.
> This is a side effect of some extremely clever optimizations it
> performs for Inanium VI processors, taking advantage of the
^^^^^^^

Is this an intentional jab at Intel? ;)

Christian Bau

unread,
Jan 22, 2001, 9:33:52 AM1/22/01
to
In article <F3Xa6.3155$9v2....@quark.idirect.com>, "Craig Barkhouse"
<cr...@wanware.com> wrote:

"Any similarity ... is not intentional, but unavoidable."

And of course the Itanium is a highly sophisticated chip which relies
heavily on sophisticated compiler optimisations to get performance, and
also relies on the compiler to produce correct code, so it is a good
source for examples where undefined behavior really goes wrong. And if
Itanium is successful then the situation will get worse or better,
depending on your point of view.

Sergei

unread,
Jan 22, 2001, 10:08:45 AM1/22/01
to
Chris Torek <to...@elf.bsdi.com> wrote in message news:94gm48$l61$1...@elf.bsdi.com...

> >> In some cases it is definitely too hard to tell whether there is a
> >> problem. For instance:
> >> a[*p++] = a[*q++] * 2;
>
> Sergei <ser...@summertime.mtu-net.ru> writes:
> >In fact it's quite easy!
> >This is valid code with perfectly defined behaviour.
>
> As Ben Pfaff noted, I forgot to parenthesize -- the line should have
> read:
>
> a[(*p)++] = a[(*q)++] * 2;
>
> so that the integers, not the pointers, are post-incremented.

This definitely clears things up!

Sergei

Keith Thompson

unread,
Jan 22, 2001, 7:46:58 PM1/22/01
to
"Craig Barkhouse" <cr...@wanware.com> writes:
> "Keith Thompson" <k...@cts.com> wrote in message
> news:yecitna...@king.cts.com...
> > gcc version 4.17, released in 2023, sets i to 1 and a[] to {11,12,3}.
> > This is a side effect of some extremely clever optimizations it
> > performs for Inanium VI processors, taking advantage of the
>
> Is this an intentional jab at Intel? ;)

That's undefined.

--
Keith Thompson (The_Other_Keith) k...@cts.com <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
MAKE MONEY FAST!! DON'T FEED IT!!

Mark Gordon

unread,
Jan 23, 2001, 2:27:56 AM1/23/01
to

I would like a compiler options that make the compiler report as many
instances of undefined, unspecified and implementation defined
behaviour as possible as errors.
--
Mark Gordon
Dyslexic C Programmer,
At least the compiler ensures I spell variable names consistently wrong.
For a faster email response replace spamtrap with mark.gordon

Dik T. Winter

unread,
Jan 23, 2001, 6:00:11 AM1/23/01
to
In article <94f1mj$j95$1...@elf.bsdi.com> to...@elf.bsdi.com (Chris Torek) writes:
> In article <3A6B04E0...@veenhoven.com>
> willem veenhoven <wil...@veenhoven.com> writes:
> >So why do most (if not all) compilers just evaluate and execute the
> >statement ...
> >... and produce a consistent result without any warning?
> >And why is that result also the same for gcc, VC and BCC on top of
> >that, which seems to indicate that there is some consensus on 'whatever
> >becomes naturally'?
...

> It is definitely just coincidence.

Indeed.


> % cc foo.c
> % ./a.out
> i: 1 a: {3, 2, 3, 4}
> % cc -O foo.c
> % ./a.out
> i: 4 a: {3, 2, 3, 4}

I got the following with two variants of the same compiler (gcc):
no opt -O
2.7.2.1 i: 4 a: {9, 2, 3, 4} i: 4 a: {3, 2, 3, 4}
2.95.1 i: 1 a: {3, 2, 3, 4} i: 4 a: {3, 2, 3, 4}

Three different results! I suspect Chris used a variant of gcc similar to
my second variant.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

Dan Pop

unread,
Jan 23, 2001, 11:47:34 AM1/23/01
to

>I would like a compiler options that make the compiler report as many
>instances of undefined, unspecified and implementation defined
>behaviour as possible as errors.

I doubt you'd want the expression i + j + k to generate an error because
the order of evaluation is unspecified. Or returning *anything* from main
or calling exit with *any* argument.

Not every form of undefined, unspecified or implementation defined
behaviour is evil. I'd like to have a compiler option enabling the
diagnostics for those forms that are, almost certainly, programming
errors, like altering the value of an object multiple times between
consecutive sequence points. But this option should not warn that

#include <unistd.h>

invokes undefined behaviour, because including this header is very
unlikely to be a programming error.

Another useful diagnostic would be about casting void pointers. This
way, (char *)malloc(foo), instead of shutting up a diagnostic, would
generate one!

Dan
--
Dan Pop
CERN, IT Division
Email: Dan...@cern.ch
Mail: CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland

brij...@my-deja.com

unread,
Feb 10, 2001, 3:02:24 AM2/10/01
to

> And why didn't you expect { 12, 2, 3, 4} ?

come to think of it i dont know why this result did not occur to me.
writing a compiler for C makes a person realise how much he does out of
habit without really thinking :)

brij:)


Sent via Deja.com
http://www.deja.com/

brij...@my-deja.com

unread,
Feb 10, 2001, 5:39:19 AM2/10/01
to
First, thank you all for the discussion.
Pardon me for not directly getting into the discussion but i really am
a baseline player with respect to these matters.

After all the advise i have got from u i have decided to implement it
in the easiest way i can and document the behavior that my compiler
will do.
Additionally I will put a STRONG recommendation to my client to
dissuade people from using such statements.

I thought i would just add the salient features of my project and why i
needed the specific answer.
My project is rewriting a compiler for ANSI C with the underlying chip
being a stack-based embedded systems chip. This chip will be used in
Avionics so trick C programming is strongly looked down upon.
The clients have very strict coding standards.
For eg. they had a lousy migration compiler which had really stupid
bugs and to get around it they had coding standards like "there should
be a comment before the end of the file" :D
Our compiler is much better than that(we are writing it in C++ and
using a concept called DGC(Dijkstra's Guarded Commands)) and i want
minimal points in the coding standards.
Nonetheless I do think that the behaviour of post increment deserves to
be in the coding std and that is going to be my recommendation.

Thanks again.
Brijesh:)

0 new messages