Valid C syntax.

P

paresh

Is this the valid C statement.

int a,b,c;
c = 5;
<<<
a = b = c;
Can anyone throw the light on this.

-Paresh
 
N

Nick Keighley

Is this the valid C statement.

int  a,b,c;
c = 5;
<<<
a = b =  c;

Can anyone throw the light on this.

it is unclear what you are asking. What is "this"?

1. the declaration and two statements above are not "a valid
statment".
They are several statments.

2. "<<<" is a syntax error

3. "a = b = c;" is a valid statement. Why wouldn't it be?

Note assignment ("=") evaluates right to left so the above
assigns c to b giving a result equal to the new b which is
then assigned to a.
 
B

Ben Bacarisse

paresh said:
Is this the valid C statement.

int a,b,c;
c = 5;
<<<
a = b = c;

Can anyone throw the light on this.

Presuming that the "<<<" and ">>>" are just there to mark the bit you
are asking about then, yes, it is valid. Both a and b are assigned
the value of c.

It is parsed as 'a = (b = c);'. The result of the right-hand b = c is
the value that b will have after the assignment and it is that
value that gets assigned to a (after any conversions). This matters
most when the types of a, b and c differ. In fact, in such a case I
would advise against an assignment like this since the effect can be
mildly confusing.
 
P

paresh

yes "<<<" and ">>>" are for marking.

I want to know that the "a = b = c;" statement is valid syntax
according to ISO C.

I ran it myself on various C/C++ compilers it worked. However some one
said to me it is not valid C syntax as
same variable cannot be l-value and r-value in same statement.

-Paresh
 
V

viza

int a,b,c;

I want to know that the "a = b = c;" statement is valid syntax according
to ISO C.

It is valid but usually stupid to use it.
It assigns the value of c to both a and b.

If the types are different the conversions become more complicated.

viza
 
C

Chris Dollin

paresh said:
yes "<<<" and ">>>" are for marking.

I want to know that the "a = b = c;" statement is valid syntax
according to ISO C.

I ran it myself on various C/C++ compilers it worked. However some one
said to me it is not valid C syntax as
same variable cannot be l-value and r-value in same statement.

Well, let's note first that in `a = b = c`, all the variables are
different, so even if the same variable couldn't be both an
lvalue and rvalue in one statement, it wouldn't matter.

Let's note next that if "some one" really did say that, they'd have
forgotten about statements like `i = i + 1;` (or `i += 1;` or `i++;`).

What I suspect they said, or thought they were saying, is that you're
not allowed [1] to update a variable /more than once/ in a single statement
(actually, before the next sequence point, but that's another discussion),
and if you update a variable, you can only read it in that same statement
(ditto) /for the purpose of determining its new value/.

So `x = x = 0;` isn't allowed. More subtly, `a = a[j] = 0;` isn't
allowed if `i == j`. Also `i = i + i++;` isn't allowed.

Finally, this isn't a matter of /syntax/ -- how to construct larger
bits of program from smaller bits -- at all. It's a matter of /semantics/,
the meaning of bits of programs. The statement `a = a[j] = 0;` is
syntactically fine. Given appropriate definitions for `a`, `i`, and `j`,
its compile-time semantics is fine too -- no constraint violation.
But to be meaningful when it's executed, `i` must not equal `j`, and
this is not a matter of syntax.

[1] On pain of undefined behaviour, ie, the program's behaviour becomes
unpredictable.
 
B

Ben Bacarisse

paresh said:
yes "<<<" and ">>>" are for marking.

I want to know that the "a = b = c;" statement is valid syntax
according to ISO C.

It is valid syntax. What is more, the semantics are well-defined too.
I ran it myself on various C/C++ compilers it worked. However some one
said to me it is not valid C syntax as
same variable cannot be l-value and r-value in same statement.

First, if this were forbidden (it is not) it would not be classed as
invalid syntax. Syntax (in C) is just about the "shape" of the code;
what sort of things can go where. Second, you were told something the
"same variable" and all yours are different so what was said has
nothing to do with your example. Third, what this person said is
obviously false, unless you think that C forbids:

x = x + 1;

in which x is used both as a lvalue and as an r-value (C does not use
the term rvalue be we can reasonably assume what was meant).
 
P

paresh

Thanks Chirs for your explanation.

That means "a=b=c;" is valid syntactically and semantically.
However if execution of the statement is right to left then it seems
that it will do what we are expecting.
On the other way (i.e left to right) it will mess up the variable "a".

Is "right to left" or "left to right" execution depends on the
compiler or its a standard?

-Paresh
 
P

paresh

It is valid syntax.  What is more, the semantics are well-defined too.


First, if this were forbidden (it is not) it would not be classed as
invalid syntax.  Syntax (in C) is just about the "shape" of the code;
what sort of things can go where.  Second, you were told something the
"same variable" and all yours are different so what was said has
nothing to do with your example.  Third, what this person said is
obviously false, unless you think that C forbids:

  x = x + 1;

in which x is used both as a lvalue and as an r-value (C does not use
the term rvalue be we can reasonably assume what was meant).

So what is the term used for rvalue in C?
Dont you think "b" is behaving as a lvalue and rvalue(whatever it is
called).

-Paresh
 
J

James Kuyper

paresh said:
yes "<<<" and ">>>" are for marking.

I want to know that the "a = b = c;" statement is valid syntax
according to ISO C.

I ran it myself on various C/C++ compilers it worked. However some one
said to me it is not valid C syntax as
same variable cannot be l-value and r-value in same statement.

Note: The C standard uses "lvalue" and "value", rather than "l-value"
and "r-value".

I think the person who told you that may have parsed this statement
incorrectly. I suspect he's thinking about it as if it was the
combination of a=b and b=c in a single statement. There is a rule which
says that, the behavior is undefined if, between two sequence points, a
value is stored in an object, and the stored value of that object is
retrieved for any purpose other than determining what the new value of
that object will be. Therefore, if you combined a=b with b=c in a single
statement without an intervening sequence point, the behavior would be
undefined. Example:

(a=b)*(b=c); // Behavior is undefined.

However, in reality, while a=b=c contains no sequence points, it is not
a combination of a=b with b=c. Instead, it is equivalent to

a = (b=c);

Every assignment expression ( =, +=, -=, *=, etc.) has a value (an
r-value, in your terms) which is the same as the value of it's left
operand after the assignment. Note that the value of an assignment can
be used immediately, even though the actual change to the stored value
of it's left operand doesn't have to happen until just before the next
sequence point. This means that the value of an assignment expression
maybe used even in circumstances, such as this one, where retrieve that
stored value would have undefined behavior.
 
J

James Kuyper

paresh wrote:
....
So what is the term used for rvalue in C?

There is exactly one use of the term "rvalue" in the C standard. It
occurs in footnote 53, in section 6.3.2.1p1. It says: "What is sometimes
called ‘‘rvalue’’ is in this International Standard described as the
‘‘value of an expression’’."
Dont you think "b" is behaving as a lvalue and rvalue(whatever it is
called).

No. The rvalue is (b=c), not b itself.
 
B

Ben Bacarisse

paresh said:
Thanks Chirs for your explanation.

That means "a=b=c;" is valid syntactically and semantically.
However if execution of the statement is right to left then it seems
that it will do what we are expecting.
On the other way (i.e left to right) it will mess up the variable "a".

Is "right to left" or "left to right" execution depends on the
compiler or its a standard?

The language standard does not specify the order of execution but
it does specify the required meaning (the semantics). As as result
you question does not really have an answer since it assumes something
matters (the execution order) when it does not.

What you write is guaranteed to mean what you think it means. b gets
set to c and a gets set the value of b = c which is defined to be the
value that b *will eventually get*.

No compiler has any wriggle room about what the effect is to be, but a
compiler is allowed to achieve this effect in any way it likes. In
your case, c was 5, so a compiler is permitted to set a to 5 (before
setting b and without ever reading the value of c) and then set b to
5. Equally it can do it in some other order and it may access c if it
chooses. The language standard simply says what the effect must be.
 
C

Chris Dollin

paresh said:
Thanks Chirs for your explanation.

That means "a=b=c;" is valid syntactically and semantically.
However if execution of the statement is right to left

It isn't (required to be).
then it seems
that it will do what we are expecting.

That depends on what you expect.
On the other way (i.e left to right) it will mess up the variable "a".

Is "right to left" or "left to right" execution depends on the
compiler or its a standard?

Right-to-left or left-to-right /execution/ is left to the implementation.
However, the statement `a = b = c;` is shorthand for `a = (b = c);`;
we usually say "= is right-associative". This isn't execution, just
syntax, and that /parse/ is demanded by the Standard.

In `a = (b = c)`, the order of evaluation of the operands `a` and `b = c`
is not specified. However `a` is evaluated for its location (what I, following
Strachey but not the C standard, would call its "lvalue") and `(b = c)` is
evaluated for its (r)value; when both operands have been evaluated,
the value of `b = c` is stored into the location `a`.

In, say, `x = i = 17;`, it clearly matters when `i` gets assigned; before
or after the evaluation of `x`? Well, it would matter, except that its
defined to be undefined behaviour; you should be able to see why from my
previous post.
 
A

Andrey Tarasevich

paresh said:
That means "a=b=c;" is valid syntactically and semantically.
However if execution of the statement is right to left then it seems
that it will do what we are expecting.
>
On the other way (i.e left to right) it will mess up the variable "a".

Is "right to left" or "left to right" execution depends on the
compiler or its a standard?

The _execution_ of this statement is not "right to left". As usual, in
absence of any sequence points C language does not impose any temporal
ordering on how a statement is executed. It can be executed right to
left, it can be executed left to right, it can be executed inside out,
it can be executed in some other weird and unusual way.

The operator '=' associates from right to left, which only means that
the grouping of operators and operands in this expression is as follows

a = (b = c)

This, in turn, tell us that 'b' should get the value of 'c' (converted
to the type of 'b') and that 'a' should get the same value as 'b' but
converted to the type of 'a'. That's it. How the compiler is going to
achieve this and in which order is up to the compiler. For example, it
can do it as follows

1. a = (A)(B) c;
2. b = (B) c;

(where 'A' and 'B' are types of 'a' and 'b' respectively). In this
scenario, as you can see, 'a' is assigned first and 'b' second, which is
opposite of what you might expect in "right to left" execution.
 
B

Ben Pfaff

Yes, if we executed

(a = b) = c;

we'd have undefined behavior, because we are attempting to modify 'a' more
than once between two sequence points.

Such a statement is a constraint violation that requires a
diagnostic, because the result of a assignment operator is not an
lvalue.
 
T

Tim Rentsch

paresh said:
Thanks Chirs for your explanation.

That means "a=b=c;" is valid syntactically and semantically.
However if execution of the statement is right to left then it seems
that it will do what we are expecting.
On the other way (i.e left to right) it will mess up the variable "a".

Is "right to left" or "left to right" execution depends on the
compiler or its a standard?

Here's a way to think of it that may be useful for a beginner.
Please note, what I'm about to say glosses over some nuances
that a strict reading of the Standard might expose, but it
should be good enough for a starting explanation.

An expression like

a = b = c;

is parsed "right associatively", that is, as

a = (b = c);

In terms of execution, what happens is

Calculate the three operands, a, b, and c,
in any order. Note that a and b are "left
hand side values", to know where to store
a value, and c is a "right hand side value",
getting an actual value from a designated
location.

The second assignment is "started", to save the value of c.

The first assignment is "started", to save the value that
is eventually destined to be in b.

Finally, changes to the variable a and the variable b take
place, but these take place in no particular order.

Even this description is a simplification, because storing something
in b could actually take place before starting the assignment to
a, or even before the calculation of the LHS a. In this example
that doesn't matter since the expression 'a' doesn't depend on
what's in the variable b, but in other cases it can.

To repeat myself, this is only an approximate explanation for
what the rules of the C standard say will happen. But if you
keep in mind that a full explanation has more to say that
isn't covered here, I think this explanation will get you
a long way towards a better understanding.
 
B

btrower

Is this the valid C statement.

int  a,b,c;
c = 5;
<<<
a = b =  c;



Can anyone throw the light on this.

-Paresh

As mentioned above, the statement is valid. It also does what you seem
to be expecting.

One thing that nobody has mentioned is whether or not you should use
such a construction. It depends. In an instance where you are setting
a bunch of variables to the same thing as a starting point, it *can*
be a good practice. Practiced C programmers will find it easy to read
and understand something like this:

{
int a, b, c, d, e, f, g, h;

a = b = c = d = e = f = g = h = 5;

}

You should not over-think what the compiler will do. Unless you are
doing something simple like the above, it is better to explicitly say
what you mean. Rather than:

a = b = c;

or

a = (b = c);

You should clearly 'say what you mean'. Not all compilers are faithful
to specifications. There is no need to expose yourself to obscure bugs
in a compiler or to errors in subsequent ports to different
languages.

In practice, I would accomplish the above in two statements if there
is any doubt as to types, side-effects, etc:

b = c;
a = b;

OR (depending upon what you are doing and how code is likely to
change)

b = c;
a = c;

I am not sure why you ask the question, but the fact you ask it at all
tells me you should likely be keeping it dead simple and doing
assignments separately as you mean them to be done.
 
P

paresh

I am not sure why you ask the question, but the fact you ask it at all
tells me you should likely be keeping it dead simple and doing
assignments separately as you mean them to be done.

I asked this question because I was told that this is not valid in C.
But it seems to be no problem with this.
Its different to write the same thing in other (may be simpler) way as
you suggested.
-Paresh
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top