Comma inside if statement in C

A

Adee

Well yesterday I came across a strange behaviour of C program i.e.

let suppose we have three integers
int a=5, b=6, c=7;

if(c>b , b>a)
printf("C is greater %d",c);


this if statment is working, I am surprised about it. Can anyone explain this feature to me. Thanks
 
J

John Gordon

In said:
Well yesterday I came across a strange behaviour of C program i.e.
let suppose we have three integers
int a=5, b=6, c=7;
if(c>b , b>a)
printf("C is greater %d",c);

this if statment is working, I am surprised about it. Can anyone explain
this feature to me. Thanks

When you have two or more expressions sepatated by commas, the rightmost
expression value is used, and all the other values are discarded.

So in this case, the expression 'c>b' is evaluated and the result is
discarded, then the expression 'b>a' is evaluated and used for the if()
statement.
 
B

Ben Bacarisse

Adee said:
Well yesterday I came across a strange behaviour of C program i.e.

let suppose we have three integers
int a=5, b=6, c=7;

if(c>b , b>a)
printf("C is greater %d",c);


this if statment is working, I am surprised about it. Can anyone
explain this feature to me. Thanks

In this context, the comma is an operator used for sequencing the
evaluation of two expressions (the comma symbol has other meanings in
other contexts). What happens is this: c>b is (pointlessly) evaluated
and the result is "thrown away". The result of the whole expression --
that of the condition being tested -- is simply the result of b>a. Did
you test with other values of c?
 
K

Keith Thompson

John Gordon said:
When you have two or more expressions sepatated by commas, the rightmost
expression value is used, and all the other values are discarded.

So in this case, the expression 'c>b' is evaluated and the result is
discarded, then the expression 'b>a' is evaluated and used for the if()
statement.

That's true only when the comma is a comma *operator*. The comma symbol
is also used in other contexts, e.g., to saparate function arguments.

The syntax of an if statement specifies that the tokens between the
parentheses are a single expression, so in

if (c>b, b>a)

that's a comma operator; `c>b` is evaluated, the result is discarded,
then `b>a` evaluated and the result is used as the condition. (The
compiler is likely to generate code that doesn't bother to evaluate
`c>b`, since it has no side effects and its result is ignored). So the
printf statement lies; the output of the program is not affected by
whether C is greater than anything.

On the other hand, if you write:

some_func(c>b, b>a)

you're passing two arguments to some_func; the first is the result of
`c>b` and the second is the result of `b>a` (each of which is either 0
or 1). That's a delimiter between arguments, *not* a comma operator.
 
X

Xavier Roche

Le 14/02/2013 20:10, Keith Thompson a écrit :
That's true only when the comma is a comma *operator*. The comma symbol
is also used in other contexts, e.g., to saparate function arguments.

It is especially important with respect to the sequence point(s):
some_func(a++, a++)
will have an undefined behavior (comma is not a sequence point)

some_func((a++, a++))
will have a defined behavior (comma is a sequence point)
(some_func takes one argument here)
 
K

Keith Thompson

Xavier Roche said:
Le 14/02/2013 20:10, Keith Thompson a écrit :

It is especially important with respect to the sequence point(s):
some_func(a++, a++)
will have an undefined behavior (comma is not a sequence point)

some_func((a++, a++))
will have a defined behavior (comma is a sequence point)
(some_func takes one argument here)

Yes, but the latter is still poor style. IMHO it's better written as:

some_func(a+1);
a += 2;

If you're writing a compiler, you have to get this stuff right. If
you're writing code, clarity is important.
 
X

Xavier Roche

Le 14/02/2013 21:13, Keith Thompson a écrit :
Yes, but the latter is still poor style. IMHO it's better written as:

Yes, of course. The only rather reasonable location of parenthesis is
probably conditions ; ie.

int success;
if (foo_is_successful()
&& (bar_process(&success), success) == TRUE
) {
....

which in many situations is simplifying the visual flow.
 
K

Keith Thompson

Xavier Roche said:
Le 14/02/2013 21:13, Keith Thompson a écrit :

Yes, of course. The only rather reasonable location of parenthesis is
probably conditions ; ie.

int success;
if (foo_is_successful()
&& (bar_process(&success), success) == TRUE
) {
...

which in many situations is simplifying the visual flow.

What I suggested was poor style was function arguments with side
effects; it wasn't particularly about parentheses. I'm not sure your
example is any better. (And the "== TRUE" is a really bad idea. If
"success" is a condition, just use it as one.)
 
K

Keith Thompson

pete said:
I think that the output of the printf statement
was most likely intended to indicate transitivity,
and therefore I also think that

if(c>b && b>a)

is what was most likely intended to be written.

Perhaps, but printing "C is greater 7" is not the clearest way to
express that condition. (Then again, it's not the clearest way to
express anything else.)
 
G

glen herrmannsfeldt

pete said:
(snip)

(snip)
If (a) has file scope and
if (a) is also accessed within the some_func function,
then
a += 2;
some_func(a - 1);
would be the semantically equivalent form.

There is also:

a++;
some_func(a);
a++;

which might be more readable in some contexts.

In written formats like PDF, you have to keep track of how
many bytes you have written up to certain points to put into
the TOC at the end.

-- glen
 
B

Ben Bacarisse

glen herrmannsfeldt said:
There is also:

a++;
some_func(a);
a++;

which might be more readable in some contexts.

Just in case it's been missed, pete's point was about the semantics, not
the readability. All three re-writes have different meanings if, as
pete stipulates, 'a' is used inside 'some_func'. His version has the
same meaning (under these conditions) as the original.

Of course, code that meets these conditions has problems that go beyond
using (a++, a++) as a single function argument!

<snip>
 
G

glen herrmannsfeldt

(snip)
Just in case it's been missed, pete's point was about the semantics, not
the readability. All three re-writes have different meanings if, as
pete stipulates, 'a' is used inside 'some_func'. His version has the
same meaning (under these conditions) as the original.

Yes, I did miss that one. I had thought about replying after Keith,
but then didn't do it. Keith commented about readability.
Of course, code that meets these conditions has problems that
go beyond using (a++, a++) as a single function argument!

Yes, don't do that!

As far as readability, if I was calling, say, 100 (different)
functions with successively higher values of a, I might go with
the a++ argument. If there was any question about readability,
one comment should apply to all of them. Seems nicer than 100
function calls and 100 a++ statements.

-- glen
 
T

Tim Rentsch

Ben Bacarisse said:
glen herrmannsfeldt said:
There is also:

a++;
some_func(a);
a++;

which might be more readable in some contexts.

Just in case it's been missed, pete's point was about the semantics,
not the readability. All three re-writes have different meanings
if, as pete stipulates, 'a' is used inside 'some_func'. His version
has the same meaning (under these conditions) as the original.
[snip]

In fact none of the three transformations mentioned are guaranteed
to be semantics preserving, pete's included. More information is
needed.

(And no, not because of something obscure like 'a' being volatile
or using the C preprocessor.)
 
B

Ben Bacarisse

pete said:
Tim said:
Ben Bacarisse said:
Keith Thompson wrote:

(snip)

some_func((a++, a++))
will have a defined behavior
(comma is a sequence point)
(some_func takes one argument here)

(snip)
some_func(a+1);
a += 2;

If you're writing a compiler, you have to get this stuff right.
If you're writing code, clarity is important.

If (a) has file scope and
if (a) is also accessed within the some_func function,
then
a += 2;
some_func(a - 1);
would be the semantically equivalent form.

There is also:

a++;
some_func(a);
a++;

which might be more readable in some contexts.

Just in case it's been missed, pete's point was about the semantics,
not the readability. All three re-writes have different meanings
if, as pete stipulates, 'a' is used inside 'some_func'. His version
has the same meaning (under these conditions) as the original.
[snip]

In fact none of the three transformations mentioned are guaranteed
to be semantics preserving, pete's included. More information is
needed.

(And no, not because of something obscure like 'a' being volatile
or using the C preprocessor.)

What did I miss?

The peculiarities of floating point arithmetic.
 
B

Ben Bacarisse

pete said:
Ben said:
pete said:
Tim Rentsch wrote:



Keith Thompson wrote:

(snip)

some_func((a++, a++))
will have a defined behavior
(comma is a sequence point)
(some_func takes one argument here)

(snip)
some_func(a+1);
a += 2;

If you're writing a compiler,
you have to get this stuff right.
If you're writing code, clarity is important.

If (a) has file scope and
if (a) is also accessed within the some_func function,
then
a += 2;
some_func(a - 1);
would be the semantically equivalent form.

There is also:

a++;
some_func(a);
a++;

which might be more readable in some contexts.

Just in case it's been missed,
pete's point was about the semantics,
not the readability. All three re-writes have different meanings
if, as pete stipulates, 'a' is used inside 'some_func'.
His version
has the same meaning (under these conditions) as the original.
[snip]

In fact none of the three transformations mentioned are guaranteed
to be semantics preserving, pete's included. More information is
needed.

(And no, not because of something obscure like 'a' being volatile
or using the C preprocessor.)

What did I miss?

The peculiarities of floating point arithmetic.

The post by Keith Thompson,
which introduced the some_func function to this thread,
showed (a) as being declared as type int in the original post.
The scope of (a) was not specifed in the original post.

It's clear that Tim Rentsch is considered the code to be separated from
the original declaration of 'a' (now long snipped) or there would have
been no need to rule out the possibility of 'a' being declared volatile.

However, my reply suggested that I knew what he was thinking of and
of course I don't. I should have ended with a question mark, not a full
stop. He will, no doubt, explain it all soon.
 
T

Tim Rentsch

Ben Bacarisse said:
pete said:
Ben said:
Tim Rentsch wrote:



Keith Thompson wrote:

(snip)

some_func((a++, a++))
will have a defined behavior
(comma is a sequence point)
(some_func takes one argument here)

(snip)
some_func(a+1);
a += 2;

If you're writing a compiler,
you have to get this stuff right.
If you're writing code, clarity is important.

If (a) has file scope and
if (a) is also accessed within the some_func function,
then
a += 2;
some_func(a - 1);
would be the semantically equivalent form.

There is also:

a++;
some_func(a);
a++;

which might be more readable in some contexts.

Just in case it's been missed,
pete's point was about the semantics,
not the readability. All three re-writes have different meanings
if, as pete stipulates, 'a' is used inside 'some_func'.
His version
has the same meaning (under these conditions) as the original.
[snip]

In fact none of the three transformations mentioned are guaranteed
to be semantics preserving, pete's included. More information is
needed.

(And no, not because of something obscure like 'a' being volatile
or using the C preprocessor.)

What did I miss?

The peculiarities of floating point arithmetic.

The post by Keith Thompson,
which introduced the some_func function to this thread,
showed (a) as being declared as type int in the original post.
The scope of (a) was not specifed in the original post.

It's clear that Tim Rentsch is considered the code to be separated from
the original declaration of 'a' (now long snipped) or there would have
been no need to rule out the possibility of 'a' being declared volatile.

Right. There wasn't any mention of int, or declaration of a, in
Xavier Roche's post, which I took to be the head of the subthread
(and consequently is as far back as I checked). Moreover, the
mention of 'a' possibly being global seems to assume a different
context than those earlier postings, which gave the impression
(to me anyway) that 'a' was declared in block scope. (Or there
may have been a nested declaration hiding the outer 'a'.)
However, my reply suggested that I knew what he was thinking of and
of course I don't. I should have ended with a question mark, not a full
stop. He will, no doubt, explain it all soon.

Actually I didn't think of floating point types. If I had I
might have mentioned them along with volatile etc -- a problem in
theory, but unlikely to occur in practice.

A more typical case, and one relatively likely to occur in actual
code, is when 'a' has a type like unsigned char or unsigned
short. If the value of a is about to wrap around, 'a++' is (in
most implementations) not the same as '(a += 1)-1', because of
integer type promotion rules.
 
T

Tim Rentsch

pete said:
Tim said:
[.. alternative was of expressing a call like foo( (a++,a++) ) ..]

In fact none of the three transformations mentioned are guaranteed
to be semantics preserving, pete's included. More information is
needed.

(And no, not because of something obscure like 'a' being volatile
or using the C preprocessor.)

What did I miss?

Explanation given in response to Ben Bacarisse's post downthread.
 
S

Shao Miller

Well yesterday I came across a strange behaviour of C program i.e.

let suppose we have three integers
int a=5, b=6, c=7;

if(c>b , b>a)
printf("C is greater %d",c);


this if statment is working, I am surprised about it. Can anyone explain this feature to me. Thanks

A comma operator is a binary operator, with a left and a right operand.
The value of the result of the comma operator is the value of the
right operand. So:

(1, 0) == 0
(0, 1) == 1
(13, 42) == 42

So:

(c > b, b > a) == (b > a)

Maybe you would be more interested in the logical operators, such as
'&&' and '||'.

(c > b && b > a) == 1

in your code example, above.
 
K

Keith Thompson

Adee said:
Well yesterday I came across a strange behaviour of C program i.e.

let suppose we have three integers
int a=5, b=6, c=7;

if(c>b , b>a)
printf("C is greater %d",c);


this if statment is working, I am surprised about it. Can anyone
explain this feature to me. Thanks

Where did you come across this? Did you write the code yourself? What
exactly did you expect it to do?

C makes it very easy to make mistakes that radically alter the meaning
of a piece of code without making it illegal.

We can speculate that what you really wanted to write was:

if (c > b && b > a)

but we can't be sure of that if you don't tell us.

We can tell you exactly what a given chunk of C code actually means,
but that's only part of the picture. A programmer's task more
commonly starts with something you want to do, and asks what code
to write to accomplish it. If your goal is to learn the language
rather than to solve random little puzzles, we can be far more
helpful if you provide us with more context.

For example, if my guess about what you were trying to do is correct,
you might have asked:

Given
int a=5, b=6, c=7;
I want to test whether the value of b is between the values of a
and c. I was surprised to find that this:
if (c > b, b > a)
actually works. Can you explain why?

We could have told you both why your code behaves the way it does, and
what you should have written.

But I'm still not sure what you were really trying to accomplish. Only
you can tell us that.

The more context you can give us, the better job we can do of both
answering your direct question and giving you the knowledge that
will let you answer the next question yourself.

Also, the output of your printf call:
printf("C is greater %d",c);
will be:
C is greater 7
which is confusing (even ignoring that "c" and "C" are two different
identifiers).
 

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

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top