473,396 Members | 1,777 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

x=(x=5,11)

Is this defined or not? Some people in ##c are saying that it has to
result in x being set to 11, i'm saying it's undefined. Who's right?
May 27 '06
111 4799
Jordan Abel wrote:
2006-05-28 <<11**********************@j55g2000cwa.googlegroup s.com>>, en******@yahoo.com wrote:

Jordan Abel wrote:
On 2006-05-27, en******@yahoo.com <en******@yahoo.com> wrote:
>
> Jordan Abel wrote:
>> On 2006-05-27, pemo <us***********@gmail.com> wrote:
>> > Jordan Abel wrote:
>> >> Is this defined or not? Some people in ##c are saying that it has to
>> >> result in x being set to 11, i'm saying it's undefined. Who's right?
>> >
>> > x=(X=5,11)
>> >
>> > My reading [but what do I know!]
>> >
>> > X=paraen'ed-expression
>> >
>> > So, paraen'ed-expression must be evaluated first
>>
>> Why? The compiler doesn't need to emit code to evaluate it to know the value.
>>
>> I think that the statement
>>
>> char foo[9];
>> x=(x=sprintf(foo,"hello"),sprintf(foo," world!\n"));
>>
>> could do things in this order:
>>
>> x=8
>> x=5
>> set foo to "hello"
>> set foo to "world!\n"
>
> You're falling into the trap of arguing what a compiler
> might do rather than what a compiler is obliged to do
> by the Standard.

The "as if" rule applies.


Yes, and the code you posted doesn't behave as if
it were executed by the abstract machine.


The behavior of the abstract machine is not defined by the standard in
this case.


In the abstract machine, the behaviour is well-defined, since getting
the result of the , operator requires getting the result of the right
operand, and since the evaluation of the outer = operator cannot cross
a sequence point, it must happen in whole only after the sp introduced
by the , operator.

May 29 '06 #51
Robert Gamble wrote:

Kenneth Brody wrote:
Robert Gamble wrote: [...]
6.5.16.1p2:
"In simple assignment (=), the value of the right operand is converted
to the type of the
assignment expression and replaces the value stored in the object
designated by the left
operand."

Now how is it possible to obtain the value of the right operand and
convert it to the type of the assignment expression without evaluting
it before you store the result in x?


Well, "the value of the right operand" can be determined without
necessarily introducing all of the side effects. Extending that
logic, the following should be "defined" as well:

x = (x++,11);


Right, and it is.


I keep forgetting that the comma operator is a sequence point, probably
because I would never write code such as the above. That, and it comes
up here with "f(x++,x++)" and people have to point out that the comma
here is not "the comma operator".

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

May 29 '06 #52
Harald van D?k said:
a, b, and c may be evaluated in any order, but the code *must* behave
as if the addition is done before the subtraction. The subtraction may
be done before the addition if and only if in every case, the same
result is generated, because otherwise the as-if rule doesn't apply.
Personally, I don't think a conforming program can tell the difference.
(See also 5.1.2.3#14.)


Examples are not normative, but I do take your point.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
May 29 '06 #53
Groovy hepcat Old Wolf was jivin' on 28 May 2006 15:35:46 -0700 in
comp.lang.c.
Re: x=(x=5,11)'s a cool scene! Dig it!
Richard Heathfield wrote:
en******@yahoo.com said:
> In the expression a + b - c, the evaluation of + must precede the
> evaluation of - in the abstract machine.


In the expression a + b - c, the abstract machine is under no obligation to
evaluate + before - or vice versa. Indeed, even a, b, and c themselves
might be evaluated in any order.


I disagree. If the expression is 5 + 6 - 3, then the machine must
compute 5 + 6 before it subtracts 3 (notwithstanding the as-if rule).

I'm not sure what other possibility you are trying to allow for here?


You're confusing order of evaluation with the parsing rules that
determine the grouping of sub-expressions. The expression 5 + 6 - 3
must be parsed as (5 + 6) - 3, but that doesn't mean the 5 + 6
sub-expression must be evaluated first.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
May 29 '06 #54
Peter "Shaggy" Haywood wrote:
Groovy hepcat Old Wolf was jivin' on 28 May 2006 15:35:46 -0700 in
comp.lang.c.
Re: x=(x=5,11)'s a cool scene! Dig it!
Richard Heathfield wrote:
en******@yahoo.com said:

> In the expression a + b - c, the evaluation of + must precede the
> evaluation of - in the abstract machine.

In the expression a + b - c, the abstract machine is under no obligation to
evaluate + before - or vice versa. Indeed, even a, b, and c themselves
might be evaluated in any order.


I disagree. If the expression is 5 + 6 - 3, then the machine must
compute 5 + 6 before it subtracts 3 (notwithstanding the as-if rule).

I'm not sure what other possibility you are trying to allow for here?


You're confusing order of evaluation with the parsing rules that
determine the grouping of sub-expressions. The expression 5 + 6 - 3
must be parsed as (5 + 6) - 3, but that doesn't mean the 5 + 6
sub-expression must be evaluated first.


Regardless of which part of the expression is evaluated first, the
addition must occur before the subtraction, I think this is Old Wolf
was trying to convey.

Robert Gamble

May 29 '06 #55
Jordan Abel wrote:
Jordan Abel wrote:

There is no part of the expression x=(x=5,11) that is not reached.


Jordan, in all your posts on this thread you seem to ignore
the fact that the comma operator introduces a sequence point.


Sequence points are fine, as far as they go, but you're forgetting that
they define a partial ordering.


The phrase "partial ordering" is not used by the Standard. Can you
explain what you mean, and provide supporting quotes?

The following quotes are relevant:

C99 6.5.16#3 (Assignment operator)
The side effect of updating the stored value of the left operand
shall occur between the previous and the next sequence point.

C99 6.5.17#2
The left operand of a comma operator is evaluated as a void
expression; there is a sequence point after its evaluation. Then
the right operand is evaluated; the result has its type and value

C99 5.1.2.3#2
At certain specified points in the execution sequence called
sequence points, all side effects of previous evaluations shall
be complete and no side effects of subsequent evaluations
shall have taken place.

Old Wolf's lemma:
The right operand of the assignment operator must be evaluated
before the assignment operator's side-effect can take place.

We are evaluating the expression (x = 5, 11).
6.5.17#2 says that there is a sequence point after (x=5) is
evaluated and before "11" is evaluated.
5.1.2.3#2 and 6.5.16#3 both say that the side-effect of (x=5)
must be complete before this sequence point.
Old Wolf's lemma says that storing the result of (x=5, 11)
in x must occur after (x=5,11) is evaluated.

Therefore, according to 6.5.16#3 and 5.1.2.3#2, at the comma
operator sequence point, x=5's side effect must be complete
and x=11's side effect must not be complete.

The only way you can deny this argument is to deny my
lemma; so you are claiming that in the situation:

x = (expression)

the side-effect of updating x can occur before (expression) is
evaluated.

Agree?

This is absurd. For example:

x = 1;
x = (printf("x is %d\n", x), 11);

Do you still call this undefined and can it print 11?

How about
int f() { printf("x is %d\n", x); return 11; }
...
x = 1;
x = f();

How far can you draw your bow?

May 29 '06 #56
On 27 May 2006 21:45:55 GMT, Jordan Abel <ra*******@gmail.com> wrote
in comp.lang.c:
On 2006-05-27, en******@yahoo.com <en******@yahoo.com> wrote:

Richard Tobin wrote:
In article <11**********************@j33g2000cwa.googlegroups .com>,
Robert Gamble <rg*******@gmail.com> wrote:

>> >> > x=(x=5,11);

>"In simple assignment (=), the value of the right operand is
>converted to the type of the assignment expression and replaces the
>value stored in the object designated by the left operand."

>Now how is it possible to obtain the value of the right operand and
>convert it to the type of the assignment expression without evaluting
>it before you store the result in x?

Clearly it's not possible to store the result before evaluating it,
but it's possible (indeed, easy!) to determine the value of (x=5,11)
before performing the assignment of 5 to x.


No, it isn't, because of the sequence point rule for the comma
operator.


Repeat after me:

Sequence points define a partial ordering.


Wrong, a sequence point defines a total ordering as defined by the
standard.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
May 29 '06 #57
Peter "Shaggy" Haywood wrote:
Old Wolf wrote:
I disagree. If the expression is 5 + 6 - 3, then the machine must
compute 5 + 6 before it subtracts 3 (notwithstanding the as-if rule).

I'm not sure what other possibility you are trying to allow for here?


You're confusing order of evaluation with the parsing rules that
determine the grouping of sub-expressions. The expression 5 + 6 - 3
must be parsed as (5 + 6) - 3, but that doesn't mean the 5 + 6
sub-expression must be evaluated first.


Well, what are you going to subtract 3 from if you have
not yet computed (5 + 6) ?

Richard Heathfield quoted:
the order of evaluation of subexpressions and the
order in which side effects take place are both unspecified.

Nevertheless, I think there are other constraints, although I
cannot find supporting text in the standard (I posted to
comp.std.c asking). Specifically, that you cannot evaluate
(ie. obtain the value of) an expression containing an operator,
until you have evaluated any applicable operands of that operator.

(By 'any applicable' I exclude cases where there are operands
which are never evaluated, eg. with && or sizeof).

Richard, please answer the above question if you can.
Another example:

x = getchar();

Does the user have to press a key before a value can be
stored in 'x'?

I contend that the assignment operator cannot be evaluated
until getchar() has been evaluated (ie. called).

May 29 '06 #58
2006-05-29 <ia********************************@4ax.com>, Jack Klein wrote:
On 27 May 2006 21:45:55 GMT, Jordan Abel <ra*******@gmail.com> wrote
in comp.lang.c:
On 2006-05-27, en******@yahoo.com <en******@yahoo.com> wrote:
>
> Richard Tobin wrote:
>> In article <11**********************@j33g2000cwa.googlegroups .com>,
>> Robert Gamble <rg*******@gmail.com> wrote:
>>
>> >> >> > x=(x=5,11);
>>
>> >"In simple assignment (=), the value of the right operand is
>> >converted to the type of the assignment expression and replaces the
>> >value stored in the object designated by the left operand."
>>
>> >Now how is it possible to obtain the value of the right operand and
>> >convert it to the type of the assignment expression without evaluting
>> >it before you store the result in x?
>>
>> Clearly it's not possible to store the result before evaluating it,
>> but it's possible (indeed, easy!) to determine the value of (x=5,11)
>> before performing the assignment of 5 to x.
>
> No, it isn't, because of the sequence point rule for the comma
> operator.


Repeat after me:

Sequence points define a partial ordering.


Wrong, a sequence point defines a total ordering as defined by the
standard.


The ordering provided by sequence points is manifestly partial.

f((a,b),(c,d));

Assuming a, b, c, d are all expressions with side-effects:

which is evaluated before the other, a or d?

There's a sequence point - there are even two of them [three if you know
where to look]. So clearly you should be able to know from that which of
the following orders abcd acbd acdb cdab cadb cabd is used.
May 29 '06 #59
>> Sequence points are fine, as far as they go, but you're forgetting that
they define a partial ordering.
The phrase "partial ordering" is not used by the Standard. Can you
explain what you mean, and provide supporting quotes?


A partial ordering is an ordering inposed on a sequence of events
by constraints of the form (X occurs before Y), (or more explicitly,
X finishes occurring before Y starts) but which does not totally
determine the order of the events.

One of the more obvious things that I don't think the standard
states is that an operator cannot be evaluated until its operands
have been evaluated, unless it's one of the C operators that
conditionally may not evaluate one of its operands (and these impose
sequence points anyway).

You call a more specific version of this applied to an assignment
operator "Old Wolf's Lemma" below.

For example: a + b cannot be evaluated until after you evaluate
both a and b, but the relative ordering of the evaluation of a
and b is not specified.
The following quotes are relevant:

C99 6.5.16#3 (Assignment operator)
The side effect of updating the stored value of the left operand
shall occur between the previous and the next sequence point.

C99 6.5.17#2
The left operand of a comma operator is evaluated as a void
expression; there is a sequence point after its evaluation. Then
the right operand is evaluated; the result has its type and value

C99 5.1.2.3#2
At certain specified points in the execution sequence called
sequence points, all side effects of previous evaluations shall
be complete and no side effects of subsequent evaluations
shall have taken place.

Old Wolf's lemma:
The right operand of the assignment operator must be evaluated
before the assignment operator's side-effect can take place.
Also, the LEFT operand of the assignment operator must be evaluated
before the assignment operator's side-effect can take place.
We are evaluating the expression (x = 5, 11).
6.5.17#2 says that there is a sequence point after (x=5) is
evaluated and before "11" is evaluated.
5.1.2.3#2 and 6.5.16#3 both say that the side-effect of (x=5)
must be complete before this sequence point.
Old Wolf's lemma says that storing the result of (x=5, 11)
in x must occur after (x=5,11) is evaluated.
Old Wolf's lemma does NOT rule out the possibility that evaluating
x (the first one in x=(x=5,11) ) occurs before, not after, the
sequence point forced by the comma operator.
Therefore, according to 6.5.16#3 and 5.1.2.3#2, at the comma
operator sequence point, x=5's side effect must be complete
and x=11's side effect must not be complete.


I'd prefer to see a statement proved that at the comma
operator sequence point, x=5's side effect must be complete
and x=11's side effect MUST NOT HAVE STARTED. But the
evaluation of x may have started before the sequence point.
I am not sure whether this is permitted to cause nuclear
explosions when run on a DeathStation 9000.
Do you think this expression causes undefined behavior:

x = x = 11;
?

In this situation, I think it can, since there is no sequence point
and the two side effects on the same variable can occur SIMULTANEOUSLY.
That the two side effects are storing the same value is not relevant.

Gordon L. Burditt
May 29 '06 #60

Gordon Burditt wrote:


Do you think this expression causes undefined behavior:

x = x = 11;
?

In this situation, I think it can, since there is no sequence point
and the two side effects on the same variable can occur SIMULTANEOUSLY.
That the two side effects are storing the same value is not relevant.

Yes, I do think it has undefined behaviour.

And rather than
x=(x=5,11);

Consider x=11; x^=(x=5,11);
Obviously this has undefined behaviour.

While it seems a bit bizarre, I know of nothing in the standard that
would prohibit a hardware implementation that needs to read a value
before storing a new value (an example might be hardware that can only
flip bits, not set/reset them) and so I expect this undefined behaviour
to extend to things like x=x=11; and x=(x=5,11);

And on this hardware, x=(x=5,11) wouldn't leave x=5 or x=11, it would
leave x with some undefined value.

This would also mean things like g=f(); where g is global and f()
modifies g would also have undefined behaviour.

Tim.

May 29 '06 #61
ri*****@cogsci.ed.ac.uk (Richard Tobin) wrote:
In article <11**********************@j33g2000cwa.googlegroups .com>,
Robert Gamble <rg*******@gmail.com> wrote:
>> > x=(x=5,11);

"In simple assignment (=), the value of the right operand is
converted to the type of the assignment expression and replaces the
value stored in the object designated by the left operand."

Now how is it possible to obtain the value of the right operand and
convert it to the type of the assignment expression without evaluting
it before you store the result in x?


Clearly it's not possible to store the result before evaluating it,
but it's possible (indeed, easy!) to determine the value of (x=5,11)
before performing the assignment of 5 to x.


Possible, but not allowed. The assignment x=5 _must_ take place (in the
abstract machine) before the sequence point; the evaluation of 11, and
therefore also the final assignment of 11 to x, must take place after
the sequence point.

Richard
May 29 '06 #62
Old Wolf said:
Peter "Shaggy" Haywood wrote:
Old Wolf wrote:
I disagree. If the expression is 5 + 6 - 3, then the machine must
compute 5 + 6 before it subtracts 3 (notwithstanding the as-if rule).

I'm not sure what other possibility you are trying to allow for here?
You're confusing order of evaluation with the parsing rules that
determine the grouping of sub-expressions. The expression 5 + 6 - 3
must be parsed as (5 + 6) - 3, but that doesn't mean the 5 + 6
sub-expression must be evaluated first.


Well, what are you going to subtract 3 from if you have
not yet computed (5 + 6) ?


You could subtract it from 0 and hold it as a temporary value:

tmp = 0 - 3
x = 0 + 5
y = 0 + 6
r = 0
r += x
r += y
r += tmp
Richard Heathfield quoted:
the order of evaluation of subexpressions and the
order in which side effects take place are both unspecified.

Nevertheless, I think there are other constraints, although I
cannot find supporting text in the standard (I posted to
comp.std.c asking). Specifically, that you cannot evaluate
(ie. obtain the value of) an expression containing an operator,
until you have evaluated any applicable operands of that operator.
Oh, but you can - see above, where tmp represents a complete evaluation of
the subtrahend and the subtraction. No further explicit subtraction
operations are carried out, although there is of course an implicit
subtraction involved in adding -3 to r.
Another example:

x = getchar();

Does the user have to press a key before a value can be
stored in 'x'?


No. I'll let you think about that one. :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
May 29 '06 #63
In article <44****************@news.xs4all.nl>,
Richard Bos <rl*@hoekstra-uitgeverij.nl> wrote:
Clearly it's not possible to store the result before evaluating it,
but it's possible (indeed, easy!) to determine the value of (x=5,11)
before performing the assignment of 5 to x.
Possible, but not allowed. The assignment x=5 _must_ take place (in the
abstract machine) before the sequence point; the evaluation of 11, and
therefore also the final assignment of 11 to x, must take place after
the sequence point.


After checking the standard, I think you're right. The result must
be as if the x=5 assignment was performed before the evaluation of 11
and therefore before the other assignment.

-- Richard
May 29 '06 #64
Gordon Burditt wrote:

Old Wolf's lemma does NOT rule out the possibility that evaluating
x (the first one in x=(x=5,11) ) occurs before, not after, the
sequence point forced by the comma operator.
Correct. But the evaluation of the left-hand operand of the
assignment operator does not cause the value of x to be
read or written, so it does not fall foul of the rule about UB
due to multiple reads/writes between sequence points.

I didn't mention this as it is a red herring compared to
the main issue.

However, this code would certainly be undefined, for the reason
you mention:

*p = (p = q, 11);

where p and q are valid pointers to int.
I'd prefer to see a statement proved that at the comma
operator sequence point, x=5's side effect must be complete
and x=11's side effect MUST NOT HAVE STARTED. But the
evaluation of x may have started before the sequence point.
The evaluation of an operator's operands, does not mean that
the evaluation of the operator has started. In fact, my lemma
is that the assignment operator cannot be evaluated until
its right-hand operand has been evaluated (although the left
hand one may be evaluated at any time).

Note that 'evaluating' the left hand operand of the assignment
operator means determining the adddress at which the value
will be stored (it doesn't mean reading or writing that value).
Do you think this expression causes undefined behavior:

x = x = 11;


Yes, x is modified twice between sequence points.

May 29 '06 #65

Old Wolf wrote:
Gordon Burditt wrote:

Old Wolf's lemma does NOT rule out the possibility that evaluating
x (the first one in x=(x=5,11) ) occurs before, not after, the
sequence point forced by the comma operator.


Correct. But the evaluation of the left-hand operand of the
assignment operator does not cause the value of x to be
read or written, so it does not fall foul of the rule about UB
due to multiple reads/writes between sequence points.

What about writing to memory that requires erasing before the write can
take place?

Tim.

May 29 '06 #66
On 2006-05-29 06:46, Jordan Abel wrote:
2006-05-29 <ia********************************@4ax.com>, Jack Klein wrote:
On 27 May 2006 21:45:55 GMT, Jordan Abel <ra*******@gmail.com> wrote
in comp.lang.c:
On 2006-05-27, en******@yahoo.com <en******@yahoo.com> wrote:
>
> Richard Tobin wrote:
>> In article <11**********************@j33g2000cwa.googlegroups .com>,
>> Robert Gamble <rg*******@gmail.com> wrote:
>>
>> >> >> > x=(x=5,11);
>>
>> >"In simple assignment (=), the value of the right operand is
>> >converted to the type of the assignment expression and replaces the
>> >value stored in the object designated by the left operand."
>>
>> >Now how is it possible to obtain the value of the right operand and
>> >convert it to the type of the assignment expression without evaluting
>> >it before you store the result in x?
>>
>> Clearly it's not possible to store the result before evaluating it,
>> but it's possible (indeed, easy!) to determine the value of (x=5,11)
>> before performing the assignment of 5 to x.
>
> No, it isn't, because of the sequence point rule for the comma
> operator.

Repeat after me:

Sequence points define a partial ordering.


Wrong, a sequence point defines a total ordering as defined by the
standard.


The ordering provided by sequence points is manifestly partial.

f((a,b),(c,d));

Assuming a, b, c, d are all expressions with side-effects:

which is evaluated before the other, a or d?


Not claiming to be an expert but 6.5.2.2#10

"The order of evaluation of the function designator, the actual
arguments, and subexpressions within the actual arguments is
unspecified, but there is a sequence point before the actual call."

would suggest that the order of evaluation of the arguments is
undefined. Regarding the order of evaluation of a and b, the only thing
I can find that seems to apply would be 6.5.16#2

"The left operand of a comma operator is evaluated as a void expression;
there is a sequence point after its evaluation. *Then* the right operand
is evaluated; the result has its type and value.94) If an attempt is
made to modify the result of a comma operator or to access it after the
next sequence point, the behavior is undefined." (emphasis mine)

While it's not very clear I would suggest that the use of "Then" would
imply that the right operand is evaluated after the left.

Erik Wikström
--
"I have always wished for my computer to be as easy to use as my
telephone; my wish has come true because I can no longer figure
out how to use my telephone" -- Bjarne Stroustrup
May 29 '06 #67
go****@woodall.me.uk wrote:
Old Wolf wrote:
Gordon Burditt wrote:

Old Wolf's lemma does NOT rule out the possibility that evaluating
x (the first one in x=(x=5,11) ) occurs before, not after, the
sequence point forced by the comma operator.


Correct. But the evaluation of the left-hand operand of the
assignment operator does not cause the value of x to be
read or written, so it does not fall foul of the rule about UB
due to multiple reads/writes between sequence points.

What about writing to memory that requires erasing before the write can
take place?


Then this erasing is part of the write, and there may not be a sequence
point during a write (or during any "side effect", even).

May 29 '06 #68

Jordan Abel wrote:
2006-05-28 <<11**********************@j55g2000cwa.googlegroup s.com>>, en******@yahoo.com wrote:

Jordan Abel wrote:
On 2006-05-27, en******@yahoo.com <en******@yahoo.com> wrote:
>
> Jordan Abel wrote:
>> On 2006-05-27, pemo <us***********@gmail.com> wrote:
>> > Jordan Abel wrote:
>> >> Is this defined or not? Some people in ##c are saying that it has to
>> >> result in x being set to 11, i'm saying it's undefined. Who's right?
>> >
>> > x=(X=5,11)
>> >
>> > My reading [but what do I know!]
>> >
>> > X=paraen'ed-expression
>> >
>> > So, paraen'ed-expression must be evaluated first
>>
>> Why? The compiler doesn't need to emit code to evaluate it to know the value.
>>
>> I think that the statement
>>
>> char foo[9];
>> x=(x=sprintf(foo,"hello"),sprintf(foo," world!\n"));
>>
>> could do things in this order:
>>
>> x=8
>> x=5
>> set foo to "hello"
>> set foo to "world!\n"
>
> You're falling into the trap of arguing what a compiler
> might do rather than what a compiler is obliged to do
> by the Standard.

The "as if" rule applies.


Yes, and the code you posted doesn't behave as if
it were executed by the abstract machine.


The behavior of the abstract machine is not defined by the standard in
this case.


I know that's your opinion. The problem is you haven't
supported your statements with reasoning or citations from
the standard. Until you do, I don't see any reason to give
your comments any further consideration.

May 29 '06 #69

Tim Woodall wrote:
On 28 May 2006 13:34:28 -0700,
en******@yahoo.com <en******@yahoo.com> wrote:

Jordan Abel wrote:
On 2006-05-27, en******@yahoo.com <en******@yahoo.com> wrote:
>
> Richard Tobin wrote:
>> In article <11**********************@j33g2000cwa.googlegroups .com>,
>> Robert Gamble <rg*******@gmail.com> wrote:
>>
>> >> >> > x=(x=5,11);
>>
>> >"In simple assignment (=), the value of the right operand is
>> >converted to the type of the assignment expression and replaces the
>> >value stored in the object designated by the left operand."
>>
>> >Now how is it possible to obtain the value of the right operand and
>> >convert it to the type of the assignment expression without evaluting
>> >it before you store the result in x?
>>
>> Clearly it's not possible to store the result before evaluating it,
>> but it's possible (indeed, easy!) to determine the value of (x=5,11)
>> before performing the assignment of 5 to x.
>
> No, it isn't, because of the sequence point rule for the comma
> operator.

Repeat after me:

Sequence points define a partial ordering.


You seem to think that sequence points are the only thing
that affect the partial ordering of expression evaluation.
That's false. In the expression a + b - c, the evaluation
of + must precede the evaluation of - in the abstract
machine. And compiled code must behave as if
the abstract machine would behave.


So you think

x ^= y ^= x ^= y;

has defined behaviour? After all, just as +/- associates L to R, ^=
associates R to L.


Of course not. The order of evaluation of the operators
doesn't determine the order in which the side effects
take place. Evaluating an assignment operator causes
a store to take place, but the side effect of updating the
stored value may take place at any point before the
next sequence point (and after the assignment operator
has been evaluated).

May 29 '06 #70
Richard Heathfield wrote:
en******@yahoo.com said:
In the expression a + b - c, the evaluation of + must precede the
evaluation of - in the abstract machine.
C99, 6.5(3): Except as specified later (for the function-call (), &&, ||,
?:, and comma operators), the order of evaluation of subexpressions and the
order in which side effects take place are both unspecified.


Right. The subexpressions of - may be evaluated in any order.
But the subexpressions must be evaluated before the minus
operator is evaluated.
In the expression a + b - c, the abstract machine is under no obligation to
evaluate + before - or vice versa.
It is, because the minus operator needs the values of its operands,
and those values are produced by evaluating those subexpressions.
Indeed, even a, b, and c themselves
might be evaluated in any order.


True but irrelevant to my comment.

May 29 '06 #71
Harald van Dijk wrote:
go****@woodall.me.uk wrote:

What about writing to memory that requires erasing before the write can
take place?


Then this erasing is part of the write, and there may not be a sequence
point during a write (or during any "side effect", even).


My own view is that the pseudo-code

register = x;
erase_x;
evaluate_new_x(old_x = register);
write_x;

Is allowed by the standard.

In the example in the subject line, the "evaluate_new_x" will itself
contain an erase_x, write_x pair.
"all side effects of previous evaluations shall be complete and no side
effects of subsequent evaluations shall have taken place". I'm arguing
that the outer assignment is neither previous nor subsequent to the
evaluation of the comma operator, it is concurrent with it.
Unfortunately, I suspect it will take a DR to get this satisfied once
and for all. Fortunately, anybody who cares enough about C to be
prepared to argue whether this is, or isn't, defined would never write
code like this in practice anyway.
Incidentally, there is, I think, an appendix "Formal model of sequence
points" http://www.davros.org/c/wg14n822.txt
(http://www.davros.org/c/wg14papers.html - informative, not normative)
which I _think_ would agree that x=(x=5,11); is defined.

x=(X=5,11); /* x and X are the same, I'm just distinguishing them to
make the analysis clearer */

e1 = e2 => W(x) E(X=5,11) S1 { W(x)<S1, E(X=5,11)<S1, E(X=5,11)<W(x) }

e1 , e2 => W(x) E(X=5) S2 E(11) S1 { W(x)<S1, E(X=5)<S1, S2<S1, E(X=5)
< S2; E(X=5)<W(x), S2<W(x)}

e1 = e2 => W(x) W(X) E(5) S2 E(11) S1 { W(x)<S1, W(X)<S1, S2<S1,
W(X)<S2, W(X)<W(x) S2<W(x) }

The only valid ordering for these events given the constraints is:
W(X) S2 W(x) S1
which has a sequence point between the two writes.

(The bit I disagree with here is E(X=5,11)<W(x) => S2 < W(x). I think
this is stronger than the text of the standard requires)

Tim.

May 29 '06 #72
go****@woodall.me.uk wrote:
Harald van Dijk wrote:
go****@woodall.me.uk wrote:
>
What about writing to memory that requires erasing before the write can
take place?


Then this erasing is part of the write, and there may not be a sequence
point during a write (or during any "side effect", even).


My own view is that the pseudo-code

register = x;
erase_x;
evaluate_new_x(old_x = register);
write_x;

Is allowed by the standard.

In the example in the subject line, the "evaluate_new_x" will itself
contain an erase_x, write_x pair.
"all side effects of previous evaluations shall be complete and no side
effects of subsequent evaluations shall have taken place". I'm arguing
that the outer assignment is neither previous nor subsequent to the
evaluation of the comma operator, it is concurrent with it.


There is no parallel execution in the abstract machine, is there? Or am
I misunderstanding you?

May 29 '06 #73

Harald van Dijk wrote:
go****@woodall.me.uk wrote:
Harald van Dijk wrote:
go****@woodall.me.uk wrote:
> >
> What about writing to memory that requires erasing before the writecan
> take place?

Then this erasing is part of the write, and there may not be a sequence
point during a write (or during any "side effect", even).


My own view is that the pseudo-code

register = x;
erase_x;
evaluate_new_x(old_x = register);
write_x;

Is allowed by the standard.

In the example in the subject line, the "evaluate_new_x" will itself
contain an erase_x, write_x pair.
"all side effects of previous evaluations shall be complete and no side
effects of subsequent evaluations shall have taken place". I'm arguing
that the outer assignment is neither previous nor subsequent to the
evaluation of the comma operator, it is concurrent with it.


There is no parallel execution in the abstract machine, is there? Or am
I misunderstanding you?


Don't think there is parallel execution, no. But x=++x; according to
the same appendix has a strict ordering on writes but still has
undefined behaviour because there is no intervening sequence point
between the two writes.

There are 3 sequence points here, before the start of the expression,
the comma operator, and the end of the expression.
Call them S0, S1 and S2.

I'm saying one write must start after S0 and complete by S2, the other
write must start after S0 and complete by S1. For the outer write the
previous sequence point is S0 and the next sequence point is S2 even
though there must be a sequence point S1 between them.

What others are saying is that the sequence point S1 prohibits the
outer assignment starting before S1 because the write cannot complete
until after S1.

The standard is, IMO, ambiguous on this. for example, extracting from a
footnote:

*p++ = getchar();

it says that the actual increment of p "can occur at any time between
the previous sequence point and the next sequence point (the ;)".
However, if p++ is evaluated before the call to getchar then if
sequence points define a strict ordering then the next sequence point
is actually before the function call, not the ;

My view is that the ; is always the next sequence point for the p++
regardless of precisely when the getchar() call is made.

Tim.

May 29 '06 #74
2006-05-29 <g5****************@newsb.telia.net>, Erik Wikström wrote:
On 2006-05-29 06:46, Jordan Abel wrote:
2006-05-29 <ia********************************@4ax.com>, Jack Klein wrote:
On 27 May 2006 21:45:55 GMT, Jordan Abel <ra*******@gmail.com> wrote
in comp.lang.c:

On 2006-05-27, en******@yahoo.com <en******@yahoo.com> wrote:
>
> Richard Tobin wrote:
>> In article <11**********************@j33g2000cwa.googlegroups .com>,
>> Robert Gamble <rg*******@gmail.com> wrote:
>>
>> >> >> > x=(x=5,11);
>>
>> >"In simple assignment (=), the value of the right operand is
>> >converted to the type of the assignment expression and replaces the
>> >value stored in the object designated by the left operand."
>>
>> >Now how is it possible to obtain the value of the right operand and
>> >convert it to the type of the assignment expression without evaluting
>> >it before you store the result in x?
>>
>> Clearly it's not possible to store the result before evaluating it,
>> but it's possible (indeed, easy!) to determine the value of (x=5,11)
>> before performing the assignment of 5 to x.
>
> No, it isn't, because of the sequence point rule for the comma
> operator.

Repeat after me:

Sequence points define a partial ordering.

Wrong, a sequence point defines a total ordering as defined by the
standard.
The ordering provided by sequence points is manifestly partial.

f((a,b),(c,d));

Assuming a, b, c, d are all expressions with side-effects:

which is evaluated before the other, a or d?


Not claiming to be an expert but 6.5.2.2#10

"The order of evaluation of the function designator, the actual
arguments, and subexpressions within the actual arguments is
unspecified, but there is a sequence point before the actual call."

would suggest that the order of evaluation of the arguments is
undefined. Regarding the order of evaluation of a and b, the only thing
I can find that seems to apply would be 6.5.16#2


The fact that the standard says "there is a sequence point before the
actual call" and does NOT, for the = operator, say "there is a sequence
point before the actual assignment", is the distinction i'm trying to
point out. If it doesn't need to be said for the latter, why was it said
for the former?
"The left operand of a comma operator is evaluated as a void expression;
there is a sequence point after its evaluation. *Then* the right operand
is evaluated; the result has its type and value.94) If an attempt is
made to modify the result of a comma operator or to access it after the
next sequence point, the behavior is undefined." (emphasis mine)

While it's not very clear I would suggest that the use of "Then" would
imply that the right operand is evaluated after the left.
But that doesn't say ANYTHING about the assignment, which is _outside the
scope of the comma operator_ - just like the ordering of (a,b) with
respect to (c,d) is outside the scope of the two comma operators which are
in play there. Sequence points define a partial ordering. (any
"ordering" for which you can say "a is before b" but cannot say "a is
before (or not before) d" is partial.)
Erik Wikström

May 29 '06 #75
2006-05-29 <12*************@corp.supernews.com>, Gordon Burditt wrote:
One of the more obvious things that I don't think the standard
states
If it doesn't state it, then I don't give a damn how "obvious" it is,
it's simply not a requirement of the standard. Especially since it
states it for SOME operators (notably, the function call operator) and
omits it for others.
is that an operator cannot be evaluated until its operands
have been evaluated, unless it's one of the C operators that
conditionally may not evaluate one of its operands (and these impose
sequence points anyway).

May 29 '06 #76
go****@woodall.me.uk wrote:
Harald van Dijk wrote:
go****@woodall.me.uk wrote:
Harald van Dijk wrote:
> go****@woodall.me.uk wrote:
> > >
> > What about writing to memory that requires erasing before the write can
> > take place?
>
> Then this erasing is part of the write, and there may not be a sequence
> point during a write (or during any "side effect", even).

My own view is that the pseudo-code

register = x;
erase_x;
evaluate_new_x(old_x = register);
write_x;

Is allowed by the standard.

In the example in the subject line, the "evaluate_new_x" will itself
contain an erase_x, write_x pair.
"all side effects of previous evaluations shall be complete and no side
effects of subsequent evaluations shall have taken place". I'm arguing
that the outer assignment is neither previous nor subsequent to the
evaluation of the comma operator, it is concurrent with it.


There is no parallel execution in the abstract machine, is there? Or am
I misunderstanding you?


Don't think there is parallel execution, no. But x=++x; according to
the same appendix has a strict ordering on writes but still has
undefined behaviour because there is no intervening sequence point
between the two writes.


That's UB even completely ignoring the as-if rule for precisely the
reason you state, so it is a significantly different example.

As for the rest of your message, good points.

May 29 '06 #77
On 29 May 2006 06:32:10 -0700,
en******@yahoo.com <en******@yahoo.com> wrote:

Of course not. The order of evaluation of the operators
doesn't determine the order in which the side effects
take place. Evaluating an assignment operator causes
a store to take place, but the side effect of updating the
stored value may take place at any point before the
next sequence point (and after the assignment operator
has been evaluated).


Now we're getting somewhere.

"(and after the assignment operator has been evaluated)"

Where is this in the standard?

(a,b) + (c,d)

if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed.

This I disagree with.

It's hard to come up with a good example where this distinction matters.
Memory that requires an erase before write is the most realistic example
I can think of.

Now that I'm at home, it appears that that Formal method for determining
whether an expression has defined behaviour isn't in either C99 or C++
even as an informative appendix.

Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/
May 29 '06 #78
Tim Woodall wrote:
On 29 May 2006 06:32:10 -0700,
en******@yahoo.com <en******@yahoo.com> wrote:

Of course not. The order of evaluation of the operators
doesn't determine the order in which the side effects
take place. Evaluating an assignment operator causes
a store to take place, but the side effect of updating the
stored value may take place at any point before the
next sequence point (and after the assignment operator
has been evaluated).

Now we're getting somewhere.

"(and after the assignment operator has been evaluated)"

Where is this in the standard?


It isn't. A side-effect is part of an expression evaluation.
It may occur before or after (or at the same time as) the
value of the expression is computed.

(The point I'm making else-thread is that the side-effect
"obviously" cannot occur before the right-hand operand
has been evaluated.)
(a,b) + (c,d)

if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed.
I don't see where he is saying that.
This I disagree with.


Naturally. a's side effects must complete before b is evaluated,
and c's side effects must complete before d is evaluated; there
is no other constraint.

May 29 '06 #79
Richard Heathfield wrote:
Old Wolf said:
Peter "Shaggy" Haywood wrote:

You're confusing order of evaluation with the parsing rules that
determine the grouping of sub-expressions. The expression 5 + 6 - 3
must be parsed as (5 + 6) - 3, but that doesn't mean the 5 + 6
sub-expression must be evaluated first.


Well, what are you going to subtract 3 from if you have
not yet computed (5 + 6) ?


You could subtract it from 0 and hold it as a temporary value:

tmp = 0 - 3
x = 0 + 5
y = 0 + 6
r = 0
r += x
r += y
r += tmp
Oh, but you can - see above, where tmp represents a complete
evaluation of the subtrahend and the subtraction.


In this example you have subtracted 3 from 0, and then added
the result to (5 + 6) later. In fact you have computed

(5 + 6) + (-3)

which was not the original expression.

So my question now becomes: what are you going to
add -3 to if you have not yet computed (5+6) ?

NB. This is difficult to discuss because of the as-if rule, and
it isn't even relevant to the original topic ( + behaves
differently to = ), so if you want to drop it then that's ok :)

May 29 '06 #80
Old Wolf wrote:
Tim Woodall wrote:
On 29 May 2006 06:32:10 -0700,
en******@yahoo.com <en******@yahoo.com> wrote:

Of course not. The order of evaluation of the operators
doesn't determine the order in which the side effects
take place. Evaluating an assignment operator causes
a store to take place, but the side effect of updating the
stored value may take place at any point before the
next sequence point (and after the assignment operator
has been evaluated).


Now we're getting somewhere.

"(and after the assignment operator has been evaluated)"

Where is this in the standard?


It isn't. A side-effect is part of an expression evaluation.
It may occur before or after (or at the same time as) the
value of the expression is computed.

(The point I'm making else-thread is that the side-effect
"obviously" cannot occur before the right-hand operand
has been evaluated.)
(a,b) + (c,d)

if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed.


I don't see where he is saying that.
This I disagree with.


Naturally. a's side effects must complete before b is evaluated,
and c's side effects must complete before d is evaluated; there
is no other constraint.


Even though with the given ordering, the next sequence point after the
evaluation of b is that of the comma operator separating c and d ?

If that's how you feel, then I don't see how you can claim the
evaluation of the outer = operator in x=(x=5,11) can't start before the
operands have been fully evaluated. "Obviously" doesn't apply, since a
possible way has been given in other messages already.

May 29 '06 #81
Harald van Dijk wrote:
Old Wolf wrote:
Tim Woodall wrote:
(a,b) + (c,d)
a's side effects must complete before b is evaluated,
and c's side effects must complete before d is evaluated; there
is no other constraint.


Even though with the given ordering, the next sequence point after the
evaluation of b is that of the comma operator separating c and d ?


The sequence points could occur in either order, because the
order of evaluation of the operands of (+) is unspecified.
If that's how you feel, then I don't see how you can claim the
evaluation of the outer = operator in x=(x=5,11) can't start beforethe
operands have been fully evaluated.


I'm claiming that the side-effect of the outer = cannot occur
until the operands have been fully evaluated (with side-effects
of those evaluations not necessarily complete).

May 30 '06 #82
Old Wolf wrote:
Harald van Dijk wrote:
Old Wolf wrote:
Tim Woodall wrote:

(a,b) + (c,d)

a's side effects must complete before b is evaluated,
and c's side effects must complete before d is evaluated; there
is no other constraint.


Even though with the given ordering, the next sequence point after the
evaluation of b is that of the comma operator separating c and d ?


The sequence points could occur in either order, because the
order of evaluation of the operands of (+) is unspecified.


You snipped the relevant sentence:

"if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed."

This evaluation order is not at all required, but *IF* this is the one
that's used, does your view change any?

May 30 '06 #83

Tim Woodall wrote:
On 29 May 2006 06:32:10 -0700,
en******@yahoo.com <en******@yahoo.com> wrote:

Of course not. The order of evaluation of the operators
doesn't determine the order in which the side effects
take place. Evaluating an assignment operator causes
a store to take place, but the side effect of updating the
stored value may take place at any point before the
next sequence point (and after the assignment operator
has been evaluated).

Now we're getting somewhere.

"(and after the assignment operator has been evaluated)"

Where is this in the standard?


"Evaluation of an expression may produce side effects."
Obviously if evaluation produces the side effects, then
the side effects can't come first.
(a,b) + (c,d)

if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed.


I'm not. Both commas must be evaluated before plus. There is
no ordering between either operand of the first comma and
either operand of the second comma. When the Standard says
"the next sequence point" what it means is the first sequence
point that must come afterwards in all possible orderings. The
next sequence point after b is the sequence point of the whole
expression, regardless of evaluation order.

May 30 '06 #84

en******@yahoo.com wrote:
Tim Woodall wrote:
On 29 May 2006 06:32:10 -0700,
en******@yahoo.com <en******@yahoo.com> wrote:

Of course not. The order of evaluation of the operators
doesn't determine the order in which the side effects
take place. Evaluating an assignment operator causes
a store to take place, but the side effect of updating the
stored value may take place at any point before the
next sequence point (and after the assignment operator
has been evaluated).

Now we're getting somewhere.

"(and after the assignment operator has been evaluated)"

Where is this in the standard?


"Evaluation of an expression may produce side effects."
Obviously if evaluation produces the side effects, then
the side effects can't come first.


But they can come during.
(a,b) + (c,d)

if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed.


I'm not. Both commas must be evaluated before plus. There is
no ordering between either operand of the first comma and
either operand of the second comma. When the Standard says
"the next sequence point" what it means is the first sequence
point that must come afterwards in all possible orderings. The
next sequence point after b is the sequence point of the whole
expression, regardless of evaluation order.


So does this have undefined behaviour, or implementation defined
behaviour?

#include <stdio.h>

int* f(int x)
{
static int d[4];
static int done[4];
static int twice;
done[x]=1;
if(x==2 && done[0] && done[1])
twice=1;
if(x==3 && twice)
return &d[1];
else
return &d[x];
}

int main(void)
{
printf("%d\n", ( (*f(0))++, (*f(1))++ ) + ( (*f(2))++, (*f(3))++ )
);
return 0;
}
FYI:
$ gcc -W -Wall -ansi -pedantic -O2 -o test test.c
$ ./test
1
$

Despite gcc doing a then b then c then d, I'm saying that this is
undefined behaviour because the sequence point at the second comma does
not limit when the side effects of b can occur and so can overlap with
the side effects of d.

Tim.

May 30 '06 #85
Harald van Dijk wrote:
>> (a,b) + (c,d)
You snipped the relevant sentence:


Sorry -- I misread
"if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed."
Yes: if b is evaluated before c, then b's side effect must complete
before d is evaluated.
This evaluation order is not at all required, but *IF* this is the one
that's used, does your view change any?


No. This doesn't exclude the possibility:
- evaluate a
- evaluate c
- evaluate d
- evaluate b
- b's side effect
- d's side effect

May 31 '06 #86
On 29 May 2006 07:14:23 -0700, go****@woodall.me.uk wrote:
<snip>
Incidentally, there is, I think, an appendix "Formal model of sequence
points" http://www.davros.org/c/wg14n822.txt
(http://www.davros.org/c/wg14papers.html - informative, not normative)
which I _think_ would agree that x=(x=5,11); is defined.

Several versions of a formal model were attempted during the C99
process, but apparently none of them got enough support to be adopted.

- David.Thompson1 at worldnet.att.net
Jun 8 '06 #87

go****@woodall.me.uk wrote:
en******@yahoo.com wrote:
Tim Woodall wrote:
On 29 May 2006 06:32:10 -0700,
en******@yahoo.com <en******@yahoo.com> wrote:
>
> Of course not. The order of evaluation of the operators
> doesn't determine the order in which the side effects
> take place. Evaluating an assignment operator causes
> a store to take place, but the side effect of updating the
> stored value may take place at any point before the
> next sequence point (and after the assignment operator
> has been evaluated).
>

Now we're getting somewhere.

"(and after the assignment operator has been evaluated)"

Where is this in the standard?
"Evaluation of an expression may produce side effects."
Obviously if evaluation produces the side effects, then
the side effects can't come first.


But they can come during.


Evaluation of operators are point events. See Wojtek's
explanation in comp.std.c.
(a,b) + (c,d)

if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed.


I'm not. Both commas must be evaluated before plus. There is
no ordering between either operand of the first comma and
either operand of the second comma. When the Standard says
"the next sequence point" what it means is the first sequence
point that must come afterwards in all possible orderings. The
next sequence point after b is the sequence point of the whole
expression, regardless of evaluation order.


So does this have undefined behaviour, or implementation defined
behaviour?

#include <stdio.h>

int* f(int x)
{
static int d[4];
static int done[4];
static int twice;
done[x]=1;
if(x==2 && done[0] && done[1])
twice=1;
if(x==3 && twice)
return &d[1];
else
return &d[x];
}

int main(void)
{
printf("%d\n", ( (*f(0))++, (*f(1))++ ) + ( (*f(2))++, (*f(3))++ )
);
return 0;
}


Undefined behavior.
FYI:
$ gcc -W -Wall -ansi -pedantic -O2 -o test test.c
$ ./test
1
$

Despite gcc doing a then b then c then d, I'm saying that this is
undefined behaviour because the sequence point at the second comma does
not limit when the side effects of b can occur and so can overlap with
the side effects of d.


Correct.

Jun 19 '06 #88

Old Wolf wrote:
Harald van Dijk wrote:
>>> (a,b) + (c,d)

You snipped the relevant sentence:


Sorry -- I misread
"if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed."


Yes: if b is evaluated before c, then b's side effect must complete
before d is evaluated.


Sorry, that isn't right. The terms "previous sequence point"
and "next sequence point" are to be read as a logical relationship
based on the abstract syntax tree, not a temporal relationship
based on any particular execution order.

Jun 19 '06 #89
en******@yahoo.com wrote:
Old Wolf wrote:
Harald van Dijk wrote:
> >>> (a,b) + (c,d)
You snipped the relevant sentence:


Sorry -- I misread
"if an example implementation evaluates a then b then c then d then you
seem to be saying that the sequence point after c but before d means
that all the side effects of evaluating b will have completed."


Yes: if b is evaluated before c, then b's side effect must complete
before d is evaluated.


Sorry, that isn't right. The terms "previous sequence point"
and "next sequence point" are to be read as a logical relationship
based on the abstract syntax tree, not a temporal relationship
based on any particular execution order.


So you keep asserting, even though it is clear there is disagreement
and the standard is unclear about it.

Jun 19 '06 #90
On 19 Jun 2006 09:22:13 -0700, en******@yahoo.com wrote:

go****@woodall.me.uk wrote:
en******@yahoo.com wrote:
> Tim Woodall wrote:
> > On 29 May 2006 06:32:10 -0700,
> > en******@yahoo.com <en******@yahoo.com> wrote:
> > >
> > > Of course not. The order of evaluation of the operators
> > > doesn't determine the order in which the side effects
> > > take place. Evaluating an assignment operator causes
> > > a store to take place, but the side effect of updating the
> > > stored value may take place at any point before the
> > > next sequence point (and after the assignment operator
> > > has been evaluated).
> > >
> >
> > Now we're getting somewhere.
> >
> > "(and after the assignment operator has been evaluated)"
> >
> > Where is this in the standard?
>
> "Evaluation of an expression may produce side effects."
> Obviously if evaluation produces the side effects, then
> the side effects can't come first.
But they can come during.


Evaluation of operators are point events. See Wojtek's
explanation in comp.std.c.
> > (a,b) + (c,d)
> >
> > if an example implementation evaluates a then b then c then d then you
> > seem to be saying that the sequence point after c but before d means
> > that all the side effects of evaluating b will have completed.
>
> I'm not. Both commas must be evaluated before plus. There is
> no ordering between either operand of the first comma and
> either operand of the second comma. When the Standard says
> "the next sequence point" what it means is the first sequence
> point that must come afterwards in all possible orderings. The
> next sequence point after b is the sequence point of the whole
> expression, regardless of evaluation order.


So does this have undefined behaviour, or implementation defined
behaviour?

#include <stdio.h>

int* f(int x)
{
static int d[4];
static int done[4];
static int twice;
done[x]=1;
if(x==2 && done[0] && done[1])
twice=1;
if(x==3 && twice)
return &d[1];
else
return &d[x];
}

int main(void)
{
printf("%d\n", ( (*f(0))++, (*f(1))++ ) + ( (*f(2))++, (*f(3))++ )
);
return 0;
}


Undefined behavior.


Since there are sequence points before each function call to f, why do
you think this is any worse than implementation defined behavior.
FYI:
$ gcc -W -Wall -ansi -pedantic -O2 -o test test.c
$ ./test
1
$

Despite gcc doing a then b then c then d, I'm saying that this is
undefined behaviour because the sequence point at the second comma does
not limit when the side effects of b can occur and so can overlap with
the side effects of d.


Correct.


While the comment is true, the conclusion is not. It is not the comma
operators that limit the side effects but the sequence points before
the function calls.
Remove del for email
Jun 20 '06 #91

Harald van Dijk wrote:
en******@yahoo.com wrote:
Old Wolf wrote:
Harald van Dijk wrote:
> > >>> (a,b) + (c,d)
> You snipped the relevant sentence:

Sorry -- I misread

> "if an example implementation evaluates a then b then c then d thenyou
> seem to be saying that the sequence point after c but before d means
> that all the side effects of evaluating b will have completed."

Yes: if b is evaluated before c, then b's side effect must complete
before d is evaluated.


Sorry, that isn't right. The terms "previous sequence point"
and "next sequence point" are to be read as a logical relationship
based on the abstract syntax tree, not a temporal relationship
based on any particular execution order.


So you keep asserting, even though it is clear there is disagreement
and the standard is unclear about it.


My comment is meant to be read as an explanation, not
an assertion.

However, since you're interested, read the response
to Clive Feather's DR 087, on order of evaluation.

Jun 20 '06 #92

Barry Schwarz wrote:
On 19 Jun 2006 09:22:13 -0700, en******@yahoo.com wrote:

go****@woodall.me.uk wrote:
en******@yahoo.com wrote:
> Tim Woodall wrote:
> > On 29 May 2006 06:32:10 -0700,
> > en******@yahoo.com <en******@yahoo.com> wrote:
> > >
> > > Of course not. The order of evaluation of the operators
> > > doesn't determine the order in which the side effects
> > > take place. Evaluating an assignment operator causes
> > > a store to take place, but the side effect of updating the
> > > stored value may take place at any point before the
> > > next sequence point (and after the assignment operator
> > > has been evaluated).
> > >
> >
> > Now we're getting somewhere.
> >
> > "(and after the assignment operator has been evaluated)"
> >
> > Where is this in the standard?
>
> "Evaluation of an expression may produce side effects."
> Obviously if evaluation produces the side effects, then
> the side effects can't come first.

But they can come during.


Evaluation of operators are point events. See Wojtek's
explanation in comp.std.c.
> > (a,b) + (c,d)
> >
> > if an example implementation evaluates a then b then c then d then you
> > seem to be saying that the sequence point after c but before d means
> > that all the side effects of evaluating b will have completed.
>
> I'm not. Both commas must be evaluated before plus. There is
> no ordering between either operand of the first comma and
> either operand of the second comma. When the Standard says
> "the next sequence point" what it means is the first sequence
> point that must come afterwards in all possible orderings. The
> next sequence point after b is the sequence point of the whole
> expression, regardless of evaluation order.

So does this have undefined behaviour, or implementation defined
behaviour?

#include <stdio.h>

int* f(int x)
{
static int d[4];
static int done[4];
static int twice;
done[x]=1;
if(x==2 && done[0] && done[1])
twice=1;
if(x==3 && twice)
return &d[1];
else
return &d[x];
}

int main(void)
{
printf("%d\n", ( (*f(0))++, (*f(1))++ ) + ( (*f(2))++, (*f(3))++ )
);
return 0;
}


Undefined behavior.


Since there are sequence points before each function call to f, why do
you think this is any worse than implementation defined behavior.


The object d[1] can be updated more than once after all
the calls to f have completed.
FYI:
$ gcc -W -Wall -ansi -pedantic -O2 -o test test.c
$ ./test
1
$

Despite gcc doing a then b then c then d, I'm saying that this is
undefined behaviour because the sequence point at the second comma does
not limit when the side effects of b can occur and so can overlap with
the side effects of d.


Correct.


While the comment is true, the conclusion is not. It is not the comma
operators that limit the side effects but the sequence points before
the function calls.


The sequence points before the function calls don't change
anything. The function calls have to complete before the side
effects in each case, but the side effects of (*f(1))++ and
(*f(3))++ can still overlap each other. The expression

((*f(0))++, p=f(1), (*p)++) + ((*f(2))++, q=f(3), (*q)++)

also has undefined behavior, for the same reason.

Jun 20 '06 #93
en******@yahoo.com wrote:
Harald van Dijk wrote:
en******@yahoo.com wrote:
Old Wolf wrote:
> Harald van Dijk wrote:
> > > >>> (a,b) + (c,d)
> > You snipped the relevant sentence:
>
> Sorry -- I misread
>
> > "if an example implementation evaluates a then b then c then d then you
> > seem to be saying that the sequence point after c but before d means
> > that all the side effects of evaluating b will have completed."
>
> Yes: if b is evaluated before c, then b's side effect must complete
> before d is evaluated.

Sorry, that isn't right. The terms "previous sequence point"
and "next sequence point" are to be read as a logical relationship
based on the abstract syntax tree, not a temporal relationship
based on any particular execution order.


So you keep asserting, even though it is clear there is disagreement
and the standard is unclear about it.


My comment is meant to be read as an explanation, not
an assertion.

However, since you're interested, read the response
to Clive Feather's DR 087, on order of evaluation.


http://open-std.org/JTC1/SC22/WG14/www/docs/dr_087.html

Thanks. Using your interpretation of sequence points, which is the
intervening sequence point between the two assignments to g in line B?
With "previous" and "next" sequence point referring to the previous and
next in time, the expression is unspecified but not undefined with any
order of evaluation, but using your interpretation, I think the
behaviour would be undefined (and the answer is that it is not
undefined).

Jun 20 '06 #94

en******@yahoo.com wrote:
Barry Schwarz wrote:
On 19 Jun 2006 09:22:13 -0700, en******@yahoo.com wrote:

go****@woodall.me.uk wrote:
>
> #include <stdio.h>
>
> int* f(int x)
> {
> static int d[4];
> static int done[4];
> static int twice;
> done[x]=1;
> if(x==2 && done[0] && done[1])
> twice=1;
> if(x==3 && twice)
> return &d[1];
> else
> return &d[x];
> }
>
> int main(void)
> {
> printf("%d\n", ( (*f(0))++, (*f(1))++ ) + ( (*f(2))++, (*f(3))++ )
> );
> return 0;
> }

Undefined behavior.
Since there are sequence points before each function call to f, why do
you think this is any worse than implementation defined behavior.


The object d[1] can be updated more than once after all
the calls to f have completed.


I don't understand your reasoning here!

In x=(x=5,11);

I am saying that both updates of the x can start at the beginning of
the statement. The x=5 has to complete by the comma and the x=11 has to
complete at the semicolon. Hence there is a period where two updates
can be affecting the same variable at the same time.

You seem to think that the comma operator puts a limit on when the x=11
can _start_.

(fair enough - I actually think this was the intent of the standard
authors otherwise things like g=f(); where g is global and f updates it
can have unexpected results - but I think a "legal" interpretation of
the standard would allow my "clear before write" "optimization" even if
no compiler writer would actually take advantage of it)

But in my example above either d[1] gets updated exactly once or there
_must_ be an sequence point between the two updates. In this instance
you seem to have chosen my interpretation of previous and next sequence
point where a sequence point that occurs in time between two other
sequence points is not necessarily previous to one and after the other.

((*f(0))++, p=f(1), (*p)++) + ((*f(2))++, q=f(3), (*q)++)

also has undefined behavior, for the same reason.


This is completely different. If you think this is even remotely the
same as my example then you haven't understood the subtleties of my
code. Its obvious that there doesn't have to be _any_ sequence point
between the (*p)++ and the (*q)++ regardless of the evaluation order.

I had thought that we had at least got to the point where if there are
three sequence points S(0) < S(1) < S(2) (where < denotes a time
ordering) then we were debating whether the standard states that S(1)
is the next sequence point to S(0) and the previous sequence point to
S(2) but now I'm not sure what you are arguing.

If you can convince me that the standard does say this then I accept
that x=(x=5,11) has defined behaviour, as does my example above[1]. But
your "((*f(0))++, p=f(1), (*p)++) + ((*f(2))++, q=f(3), (*q)++)" still
has undefined behaviour.

Tim.

[1] defined here means my code can output 0 or 1 but nothing else.

Jun 20 '06 #95
On 20 Jun 2006 07:18:51 -0700,
go****@woodall.me.uk <go****@woodall.me.uk> wrote:

en******@yahoo.com wrote:
((*f(0))++, p=f(1), (*p)++) + ((*f(2))++, q=f(3), (*q)++)

also has undefined behavior, for the same reason.


This is completely different. If you think this is even remotely the
same as my example then you haven't understood the subtleties of my
code. Its obvious that there doesn't have to be _any_ sequence point
between the (*p)++ and the (*q)++ regardless of the evaluation order.

No. I'm wrong here. my example does always have undefined behaviour and
your example is the same.

However, we have agreed something from this (quick bit of face saving :-)

The evaluation of the left and right operands of a binary operator can
overlap.

Therefore I still contend that the writing to x=() in the subject can
overlap with the evaluation of (x=5,11), even if the final value cannot
be written until x=5 has completed.

Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/
Jun 20 '06 #96

How about?
#include <stdio.h>

unsigned int* f(int x)
{
static unsigned int d[2];
static unsigned int done[2];

done[x] = 1;

if(done[0] && d[0])
return &d[0];
else
return &d[1];
}

int main(void)
{
printf("%u\n", (*f(0))-- + (*f(1))++ );
return 0;
}

Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/
Jun 20 '06 #97
On 20 Jun 2006 03:07:02 -0700, en******@yahoo.com wrote:

Barry Schwarz wrote:
On 19 Jun 2006 09:22:13 -0700, en******@yahoo.com wrote:
>
>go****@woodall.me.uk wrote:
>> en******@yahoo.com wrote:
>> > Tim Woodall wrote:
>> > > On 29 May 2006 06:32:10 -0700,
>> > > en******@yahoo.com <en******@yahoo.com> wrote:
>> > > >
>> > > > Of course not. The order of evaluation of the operators
>> > > > doesn't determine the order in which the side effects
>> > > > take place. Evaluating an assignment operator causes
>> > > > a store to take place, but the side effect of updating the
>> > > > stored value may take place at any point before the
>> > > > next sequence point (and after the assignment operator
>> > > > has been evaluated).
>> > > >
>> > >
>> > > Now we're getting somewhere.
>> > >
>> > > "(and after the assignment operator has been evaluated)"
>> > >
>> > > Where is this in the standard?
>> >
>> > "Evaluation of an expression may produce side effects."
>> > Obviously if evaluation produces the side effects, then
>> > the side effects can't come first.
>>
>> But they can come during.
>
>Evaluation of operators are point events. See Wojtek's
>explanation in comp.std.c.
>
>> > > (a,b) + (c,d)
>> > >
>> > > if an example implementation evaluates a then b then c then d then you
>> > > seem to be saying that the sequence point after c but before d means
>> > > that all the side effects of evaluating b will have completed.
>> >
>> > I'm not. Both commas must be evaluated before plus. There is
>> > no ordering between either operand of the first comma and
>> > either operand of the second comma. When the Standard says
>> > "the next sequence point" what it means is the first sequence
>> > point that must come afterwards in all possible orderings. The
>> > next sequence point after b is the sequence point of the whole
>> > expression, regardless of evaluation order.
>>
>> So does this have undefined behaviour, or implementation defined
>> behaviour?
>>
>> #include <stdio.h>
>>
>> int* f(int x)
>> {
>> static int d[4];
>> static int done[4];
>> static int twice;
>> done[x]=1;
>> if(x==2 && done[0] && done[1])
>> twice=1;
>> if(x==3 && twice)
>> return &d[1];
>> else
>> return &d[x];
>> }
>>
>> int main(void)
>> {
>> printf("%d\n", ( (*f(0))++, (*f(1))++ ) + ( (*f(2))++, (*f(3))++ )
>> );
>> return 0;
>> }
>
>Undefined behavior.
Since there are sequence points before each function call to f, why do
you think this is any worse than implementation defined behavior.


The object d[1] can be updated more than once after all
the calls to f have completed.


I don't see how. The only way d[1] can be updated is if f() returns
its address. The expression f(1) will always return &d[1]. The
expression f(3) will return &d1 if twice is not 0. No other call to
f() will return &d[1].

Let us assume that twice is not 0 by the time f(3) is evaluated
(otherwise d1 is updated only once and we have no multiple updates at
all). The two possibilities are:

f(1) is evaluated before f(3). f(1) returns &d1. The
evaluation of f(3) obviously involves a call to the function f. There
is a sequence point before this call. That means that any side
effects of (*f(1))++ must be complete before this call. The side
effect is the update to d[1] and it is completed before the call.
Sometime after the return from f(3), d[1] is updated again but there
was a sequence point between this update and the previous one.

f(3) is evaluated before f(1). The argument is symmetrical.

The bottom line is that at each call to f, all updates to d have been
completed. After the last call to f, there is only one update to be
performed.
>> FYI:
>> $ gcc -W -Wall -ansi -pedantic -O2 -o test test.c
>> $ ./test
>> 1
>> $
>>
>> Despite gcc doing a then b then c then d, I'm saying that this is
>> undefined behaviour because the sequence point at the second comma does
>> not limit when the side effects of b can occur and so can overlap with
>> the side effects of d.
>
>Correct.


While the comment is true, the conclusion is not. It is not the comma
operators that limit the side effects but the sequence points before
the function calls.


The sequence points before the function calls don't change
anything. The function calls have to complete before the side
effects in each case, but the side effects of (*f(1))++ and
(*f(3))++ can still overlap each other. The expression


Since f(1) cannot overlap f(3) and since there is a sequence point
between the end of one call and the start of the next, whichever
expression is evaluated first must complete its side effect before the
next function call.

((*f(0))++, p=f(1), (*p)++) + ((*f(2))++, q=f(3), (*q)++)

also has undefined behavior, for the same reason.


But this is different. (*p)++ does not involve a function call and
there is no guaranteed sequence point between (*p)++ and (*q)++. The
sequence of evaluation could be
(*f(0))++
p = f(1)
(*f(2))++
q = f(3)
(*p)++
(*q)++
sum
and the penultimate two steps do in fact both update d[1] (if twice is
not 0) with no intervening sequence point.
Remove del for email
Jun 21 '06 #98

Barry Schwarz wrote:

<snip and summarize thus>

((*f(0))++, (*f(1))++) + ((*f(2))++, (*f(3))++)

(we're assuming here that f(0) is done before f(1) is done before f(2)
is done before f(3) - other orderings are allowed but are not relevant
to this discussion. f(3) returns a pointer to the same address as f(1))

I don't see how. The only way d[1] can be updated is if f() returns
its address. The expression f(1) will always return &d[1]. The
expression f(3) will return &d1 if twice is not 0. No other call to
f() will return &d[1].
(I'm using some lazy shorthand here - f(0)++ actually means (*f(0))++
etc)

because f(0) is done before f(1) and there is a comma sequence point
after f(0) and before f(1) the side effects of the f(0)++ must be
completed before f(1).

because f(2) is done before f(3) and there is a comma sequence point
after f(2)++ and before f(3) the side effects of the f(2)++ must be
completed before f(3).

But f(1) can be called before f(2) but the increment deferred until the
end of the full expression. What this does mean is that part of f(1)++
is evaluated before the various sequence points on the RHS of the +
operator and part of it is evaluated after, i.e. the evaluation of the
f(1)++ sub expression crosses sequence points.
What we are really interested in is whether the standard allows the
increment of f(1)++ to start before f(2) is called but to not complete
until the end of the full expression.
consider g++ + f(); and (g=g+1) + f(); and (g=5) + f(); where f()
modifies g. Do these have defined or undefined behaviour?

f(1) is evaluated before f(3). f(1) returns &d1. The
evaluation of f(3) obviously involves a call to the function f. There
is a sequence point before this call. That means that any side
effects of (*f(1))++ must be complete before this call. The side

The side effects of (*f(1))++ do not have to have started by the time
of the call to f(3).

Tim.

Jun 21 '06 #99
On 21 Jun 2006 02:01:21 -0700, go****@woodall.me.uk wrote:

Barry Schwarz wrote:

<snip and summarize thus>

((*f(0))++, (*f(1))++) + ((*f(2))++, (*f(3))++)

(we're assuming here that f(0) is done before f(1) is done before f(2)
is done before f(3) - other orderings are allowed but are not relevant
to this discussion. f(3) returns a pointer to the same address as f(1))

I don't see how. The only way d[1] can be updated is if f() returns
its address. The expression f(1) will always return &d[1]. The
expression f(3) will return &d1 if twice is not 0. No other call to
f() will return &d[1].
(I'm using some lazy shorthand here - f(0)++ actually means (*f(0))++
etc)

because f(0) is done before f(1) and there is a comma sequence point
after f(0) and before f(1) the side effects of the f(0)++ must be
completed before f(1).


While the comma sequence point does in fact guarantee this, the
sequence point before the call to f(1) also guarantees it. It doesn't
matter why there is a sequence point, only that there is one.

because f(2) is done before f(3) and there is a comma sequence point
after f(2)++ and before f(3) the side effects of the f(2)++ must be
completed before f(3).
As I said in the portion you chose to snip, neither f(0) nor f(2)
matter since they cannot have any effect of d[1].

But f(1) can be called before f(2) but the increment deferred until the
end of the full expression. What this does mean is that part of f(1)++
No it cannot. There is a sequence point prior to the call to f(2) and
any side effect from f(1) must be completed before this sequence
point.
is evaluated before the various sequence points on the RHS of the +
operator and part of it is evaluated after, i.e. the evaluation of the
f(1)++ sub expression crosses sequence points.
Evaluations never cross sequence points. The whole purpose of
sequence points is to insure that the evaluation is complete.


What we are really interested in is whether the standard allows the
increment of f(1)++ to start before f(2) is called but to not complete
until the end of the full expression.
The standard guarantees that all side effects are complete prior to
the sequence point. Since there is a sequence point prior to the call
to f(2), the increment must be complete.


consider g++ + f(); and (g=g+1) + f(); and (g=5) + f(); where f()
modifies g. Do these have defined or undefined behaviour?
Since evaluating g in its many forms does not involve a sequence
point, this is nothing but a red herring.

f(1) is evaluated before f(3). f(1) returns &d1. The
evaluation of f(3) obviously involves a call to the function f. There
is a sequence point before this call. That means that any side
effects of (*f(1))++ must be complete before this call. The sideThe side effects of (*f(1))++ do not have to have started by the time
of the call to f(3).


How can you state that when the standard guarantees exactly the
opposite? There is a sequence point before the call to f(3) and side
effects must be complete at the sequence point.

Tim.

Remove del for email
Jun 22 '06 #100

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Scott Beavers | last post by:
I'm trying to create a form in Excel to sort from the form and take the data to another worksheet. I am very new to this and any help would be appreciated. I have a value in a cell that will...
0
by: jason | last post by:
Hello - looking for an efficient way in perl (been a while) to use a control file to pass or fail strings submitted to a perl program. I have a flat file allow.txt in the following format. It...
5
by: Gianni Mariani | last post by:
The 3 compilers I tried all did different things. gcc 3.4.0 ICE's (Bug 15480) MS C++ 7.1 has meaningless diags Comeau accepts the code Obviously this is not somthing I'll be using until we...
16
by: Brian Tkatch | last post by:
Is there a way to check the order in which SET INTEGRITY needs to be applied? This would be for a script with a dynamic list of TABLEs. B.
28
by: FAQ server | last post by:
----------------------------------------------------------------------- FAQ Topic - How do I convert a Number into a String with exactly 2 decimal places?...
62
jkmyoung
by: jkmyoung | last post by:
Does anyone have some super, super hard Sudoku puzzles? Back in February this year, I had enough time to finally program a Sudoku solver in Java. Right now, I'm looking for solvable puzzles, but...
7
by: mandanarchi | last post by:
I found the answer last time I was 'playing' with xsl, but I didn't need to use it then and like an idiot, I didn't save where I found it. I've tried Google but it's not coming up with what I need....
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.