Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Is a[i] = i++ correct?

Reply
Thread Tools

Is a[i] = i++ correct?

 
 
Flash Gordon
Guest
Posts: n/a
 
      12-28-2007
Rick wrote, On 28/12/07 19:42:
> On Thu, 27 Dec 2007 03:45:29 -0800 (PST), jeniffer
> <> wrote:
>
>> I want to know why is a[i] = i++ ; wrong? People say that it is
>> because of different parsing during compilation.Please explain
>> technically why it is wrong/behaviour undefined?

>
> Good afternoon, Jeniffer.
>
> Looks like I'm the only one here who's going to give you a straight
> answer without chastising you first for not reading the FAQ.


Well, since it is only polite to read the FAQ first and the FAQ is more
accurate than your answer...

Actually, *you* should have read the FAQ first as well so that you could
provide correct information.

> The answer is that C does not guarantee order of evaluation.
> Therefore, i++ might be evaluated first, before being applied as an
> index into a[], or it might be evaluated last, and the compiler is
> perfectly free to do it either way.


No, that is NOT why it is undefined. As others have stated it is
undefined because i is modified and read for a reason other than
determining the new value between sequence points. This means that the
compiler is NOT restricted to the possibilities you suggested.

> So, if i started off as, say, 2, then a[i] might be a[2], or it might
> be a[3].


Or it could be 97 or cause your program to crash or anything else. Yes,
there *are* reasons it could crash a program on some possible
implementations.

> Hope this helps...


I hope I have corrected your misconceptions.
--
Flash Gordon
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      12-28-2007
Rick <> writes:
> On Thu, 27 Dec 2007 03:45:29 -0800 (PST), jeniffer
> <> wrote:
>>I want to know why is a[i] = i++ ; wrong? People say that it is
>>because of different parsing during compilation.Please explain
>>technically why it is wrong/behaviour undefined?

>
> Good afternoon, Jeniffer.
>
> Looks like I'm the only one here who's going to give you a straight
> answer without chastising you first for not reading the FAQ.


Since reading the FAQ would have answered the question, I don't see
any problem with reminding people to check it first.

> The answer is that C does not guarantee order of evaluation.
> Therefore, i++ might be evaluated first, before being applied as an
> index into a[], or it might be evaluated last, and the compiler is
> perfectly free to do it either way.
>
> So, if i started off as, say, 2, then a[i] might be a[2], or it might
> be a[3].


That's only part of the problem. The behavior is completely
undefined; a[i] might be a[42], or your left earlobe.

There are cases where C's unspecified order of evaluation doesn't lead
to undefined behavior (for example, if the two subexpressions don't
refer to any of the same variables). But in this particular case, the
standard places absolutely no restrictions on how the program can
behave.

--
Keith Thompson (The_Other_Keith) <kst->
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Kaz Kylheku
Guest
Posts: n/a
 
      12-28-2007
On Dec 28, 7:34*am, gaze...@xmission.xmission.com (Kenny McCormack)
wrote:
> Get off the "the C standard says..." horse and think logically, like a
> human being for a second, and it becomes clear. *When a human sees the
> above, they logically think:


A twit who has somehow been pushed through a computer science
undergraduate program is hardly representative of all humans.

> * * * * 1) Evaluate the RHS
> * * * * 2) Assign it to the LHS


Except, doh, the left hand side requires evaluation. To know what a[i]
refers to requires you to evaluate i.

A human being with no preconception of any of these concepts could
interpret it in various ways.

For example, strict left-to-right evaluation would be this:

1) Evaluate the left side completely to determine what location a[i]
is.
2) Evaluate the right side, performing the increment of i,
yielding the previous value.
3) Store the value to the location computed in 1.

Or, rvalue-first evaluation would be:

1) Fully evaluate the expression which produces the value to be
assigned.
2) Then evaluate the left side, if necessary, to determine
the location where the value will be stored.
3) Store the value computed in 1 into the location
computed in 3.
a human, but rather a twit who has somehow been pushed through a
computer science undergraduate program.

> in that order. *So, obviously, if i=0 on start, then at end, a[1] will


Obviously, you're a moron.
 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      12-28-2007
On Dec 28, 8:37*am, c...@tiac.net (Richard Harter) wrote:
> On Thu, 27 Dec 2007 12:13:10 +0000, Richard Heathfield
>
> <r...@see.sig.invalid> wrote:
> >jeniffer said:

>
> >> Hi

>
> >> I want to know why is *a[i] = i++ ; wrong?

>
> >What do you think it should mean? Given this code:

>
> >int a[3] = { 5, 7, 9 };
> >i = 0;
> >a[i] = i++; /* bug */

>
> >which member of a[] do you think will be updated, and to what value?

>
> If C used a left to right order of application


Then it would be a better safer language.

similar to that
> for arithmetic (with the as-if rule as a back door) then the
> results would be well defined.


But it isn't and so they are not. Your point is?


*After the statement a[0] would be
> 0 and i would be 1. *Similarly, the statements
>
> i=0;
> a[i++] = ++i + i++;
>
> would evaluate as follows:
>
> The target of the assignment is a[0].
> i is incremented after computing the location to become 1.
> On the RHS i is incremented to become 2. (++i)
> i is added to i to produce 4; once the addition is completed i is
> incremented to become 3. *(i++).
>
> Of course C does not guarantee the order of evaluation except in
> special cases, and it is important to understand that it does
> not. *One can argue that not guaranteeing the preservation of
> code order is a design flaw in the C language, but it doesn't


I would agree. Today, it's no longer a good engineering tradeoff.

What the loose order of evaluation buys you is the ability to optimize
code whose operands are accessed through indirection that can't be
analyzed at compile time.

Even the order of evaluation is well-defined, you can still optimize
code like

a[j] = i++;

quite nicely. The compiler still can change the order of actual
evaluation to make it run fast on the given CPU, because the objects
a[], i and j are distinct, non-overlapping. And, also, they are not
volatile objects. So the order in which anything takes place is not
externally visible behavior. Only the correctness of the end result
matters. It doesn't matter whether a[j] receives the value first, or
whether i receives the value first.

However, if you have indirection, like:

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

then the order matters. In C the way it is, this is undefined if p and
q point to the same memory location. But if they point to different
integers, then it's well-defined! In the general case, it is only
known at run-time whether p and q are aliased. Because of the
undefinedness of the behavior if p and q are aliased, the compiler
doesn't have to care about that case, and can generate code to do it
in any arbitrary order.

If you make the order well-defined, then the compiler has to work with
the suspicion that p and q may be the same object. That of course
affects code generation decisions. If p and q are never in fact
aliased, then that code may be less than optimal.

In modern C, we now have the "restrict" qualifier which makes code
undefined when pointers are aliased. I.e. in a C language dialect
which is like C99, but in which evaluation order is well-defined, we
could still get the undefined behavior of p and q being overlapped,
like this:

int *restrict p, * restrict q;

/* ... point them to the same thing ... */

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

The compiler can assume that p and q are not aliased and optimize the
code accordingly.

Loose evaluation order is merely an optimization crutch which was
needed before restrict qualifiers were introduced.

Speaking of optimization crutches, ultimately, what would be a good
solution would be the ability to define optimization parameters over
specific blocks of code. Suppose you had a way to express the idea
``over this block of code, please use classic loose evaluation
order''. You could have the safety benefit of well-defined order
throughout most of the program, as well as the optimization benefits
of loose order in hotspots.

So basically, the argument that loose evaluation order is a necessary
design decision for good code generation simply doesn't hold water.
It's true with regard to 1970's compiler technology, if even that.

> matter - C is cast in stone.


C is not cast in stone. Past undefined behaviors can easily be defined
in the future, without breaking any correctly written code.
 
Reply With Quote
 
christian.bau
Guest
Posts: n/a
 
      12-28-2007
On Dec 28, 7:50*pm, gaze...@xmission.xmission.com (Kenny McCormack)
wrote:
>
> christian.bau <christian....@cbau.wanadoo.co.uk> wrote:
> >Java programmers all over the world think you are completely wrong. In
> >Java, a [i] = i++; has defined behaviour. The expression is evaluated
> >from left to right. So first it evaluates the lvalue a [i], then the
> >right hand side i++. The array element changed is determined by the
> >original value of i.

>
> Well, that doesn't actually prove anything. *What it means is that Java
> defined it that way (probably because it was easier to implement) and
> the programmers accepted it. *It doesn't mean it is desirable (nor, of
> course, does it mean it is undesirable).


You actually think anything in Java is defined the way it is defined
because "it was easier to implement"? Seriously?
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      12-28-2007
Kaz Kylheku said:

> On Dec 28, 7:34 am, gaze...@xmission.xmission.com (Kenny McCormack)
> wrote:
>
>> in that order. So, obviously, if i=0 on start, then at end, a[1] will

>
> Obviously, you're a moron.


Obviously, he's a troll. A relatively recent one, though, so you might not
have caught on to him yet.

(By the way - welcome back!)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
Reply With Quote
 
Rick
Guest
Posts: n/a
 
      12-28-2007
On Fri, 28 Dec 2007 20:17:30 +0000, Flash Gordon
<> wrote:

>> I hope I have corrected your misconceptions.


Good evening, Flash.

Respectfully, there were no misconceptions. There were only partial
answers. I gave Jeniffer the answers that I thought were needed
without getting into a lot of detail that goes way beyond the scope of
my perception of the questions asked. Of course, my perception may
have been wrong.

 
Reply With Quote
 
Rick
Guest
Posts: n/a
 
      12-28-2007
On Fri, 28 Dec 2007 12:23:01 -0800, Keith Thompson <kst->
wrote:

>> So, if i started off as, say, 2, then a[i] might be a[2], or it might
>> be a[3].

>
>That's only part of the problem. The behavior is completely
>undefined; a[i] might be a[42], or your left earlobe.


Good evening, Keith.

If...

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

.... then I claim that a[ i ] will be either a[ 2 ] or a[ 3 ],
depending on whether i++ gets evaluated first or last, but it must be
either one or the other.

Wrong?
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      12-28-2007
Rick said:

<snip>

> If...
>
> i = 2;
> a[ i ] = i++;
>
> ... then I claim that a[ i ] will be either a[ 2 ] or a[ 3 ],
> depending on whether i++ gets evaluated first or last, but it must be
> either one or the other.
>
> Wrong?


Er, yeah, wrong. C doesn't actually guarantee this at all. But
realistically, how could it have any other value? Well, I don't plan to
work an example for you, but I recommend the following page, which gives
some hard data on the various results you get from different compilers for
similar expressions:

http://www.phaedsys.demon.co.uk/chri...wengtips3a.htm

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
Reply With Quote
 
Kenny McCormack
Guest
Posts: n/a
 
      12-28-2007
In article <>,
Rick <> wrote:
>On Fri, 28 Dec 2007 12:23:01 -0800, Keith Thompson <kst->
>wrote:
>
>>> So, if i started off as, say, 2, then a[i] might be a[2], or it might
>>> be a[3].

>>
>>That's only part of the problem. The behavior is completely
>>undefined; a[i] might be a[42], or your left earlobe.

>
>Good evening, Keith.
>
>If...
>
>i = 2;
>a[ i ] = i++;
>
>... then I claim that a[ i ] will be either a[ 2 ] or a[ 3 ],
>depending on whether i++ gets evaluated first or last, but it must be
>either one or the other.
>
>Wrong?


Wrong, by the standards of this newsgroup.

Here, what actually happens in the real world is irrelevant. In fact,
the real world itself is pretty much irrelevant. What matters is what
the standard requires, and the possible existence of a machine which has
read and understands the standard as well as the language lawyers
(aka, "the regulars") here have done.

So, the theory is that once you invoke "undefined behavior", anything
can happen (and does on the hypothetical machine described above),
including assigning a value to a[42] or starting global thermonuclear
war.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57