Logical And

D

Dan Pop

In said:
Umm no, I don't think so. I was merely following my instincts, which
invariably make me answer seemingly rhetorical questions.


According to the "as if" principle, a compiler is perfectly free to do
this given the right circumstances. And, in fact, it may just be the
clever thing to do.

But the point is that it can do it *only* when the program can't tell
the difference. Fortran programmers often wish they could do things
like:

if (a == 0 || b / a > 0) /* do something */ ;

The short circuiting feature of || and && is not an optimisation feature,
its purpose is to make the language easier to use. Without it, the
above statement would have to be rewritten as:

if (a == 0) /* do something */ ;
else if (b / a > 0) /* do it again */ ;

Dan
 
K

Keith Thompson

The short circuiting feature of || and && is not an optimisation feature,
its purpose is to make the language easier to use.
above statement would have to be rewritten as:

I suspect it would be more accurate to say that it's not *just* an
optimization feature. Efficiency may also have been a concern when
the feature was first designed (probably in one of C's ancestors).

It's a happy coincidence that ease of use and efficiency (on the
hardware of the time) both led to the same design decision.

I haven't looked at the relevant historical documents lately, so I'm
only guessing here.
 
D

Dan Pop

In said:
(e-mail address removed) (Dan Pop) writes:
[...]
The short circuiting feature of || and && is not an optimisation feature,
its purpose is to make the language easier to use.
above statement would have to be rewritten as:

I suspect it would be more accurate to say that it's not *just* an
optimization feature. Efficiency may also have been a concern when
the feature was first designed (probably in one of C's ancestors).

It's a happy coincidence that ease of use and efficiency (on the
hardware of the time) both led to the same design decision.

I haven't looked at the relevant historical documents lately, so I'm
only guessing here.

I was using the *present* tense, so whatever was the case when the
feature was introduced is irrelevant to my statement.

As demonstrated in this thread, depending on the context, the feature
may or may not optimise the execution speed. I suspect this has always
been the case (in trivial cases, ORing/ANDing everything together is
faster than checking the value of each operand). In principle, the
compiler should be able to detect the cases when the as-if rule allows
non-short circuiting evaluation and and take advantage of it when it
improves the execution speed, but I doubt that many compilers bother
performing such checking.

Dan
 
R

Robert Bachmann

Keith said:
If I saw code that used "if (a & b)", my first assumption would be
that it was a typo for "if (a && b)", and my second would be that the
author really intended to test the bitwise "and" of a and b.

When writing something like "if (a & b)" it is a good idea to
write "if (a & b) /*bitwise*/" instead.
On the other hand it looks a little bit funny to me, just like
some beginner who writes "int i; /*an integer variable*/" ;-)

So I for myself always use "if (a bitand b)" instead of
"if (a & b)" (after including <iso646.h> of course),
because with this notation it should be obvious to see that I
did *really* mean & and not &&.

-rb
 
M

Mark A. Odell

When writing something like "if (a & b)" it is a good idea to
write "if (a & b) /*bitwise*/" instead.

What's next? When writing this do we need the comment shown?

idx++; /* Increment 'idx' */

just because it might confuse a beginner? You, the developer must write
the code you intend to write. Why should I not believe you meant bit-AND
if you write?

if (reg_a_bits & reg_a_field_mask)

What is so wrong about C that people aren't comfortable with it?
 
K

Keith Thompson

Mark A. Odell said:
What's next? When writing this do we need the comment shown?

idx++; /* Increment 'idx' */

just because it might confuse a beginner?

No, because "idx++;" is unambiguous.

The problem with "if (a & b)" is that it's as likely to be a newbie
mistake (using "&" where "&&" is correct) as a deliberate use of
bitwise-and. I'd rather add a comment than risk having the next
maintainer of the code (who may not be as comfortable with C as I am)
"correct" the "&" to "&&".
You, the developer must write the code you intend to write. Why
should I not believe you meant bit-AND if you write?

if (reg_a_bits & reg_a_field_mask)

If the variables are called "reg_a_bits" and "reg_a_field_mask", it's
not as much of a problem. If they're called "a" and "b" -- well, they
probably shouldn't be unless it's a toy example.
 
M

Mark A. Odell

[snip]
The problem with "if (a & b)" is that it's as likely to be a newbie
mistake (using "&" where "&&" is correct) as a deliberate use of
bitwise-and. I'd rather add a comment than risk having the next
maintainer of the code (who may not be as comfortable with C as I am)
"correct" the "&" to "&&".

In my world of microcontrollers and drivers, & is more common than &&.
If the variables are called "reg_a_bits" and "reg_a_field_mask", it's
not as much of a problem. If they're called "a" and "b" -- well, they
probably shouldn't be unless it's a toy example.

So the real fix might better to continue to write C without junk comments
but to pick variable names that have meaning? I'm all for that.
 
O

Old Wolf

if(expr("1st",1) || expr("2nd",0) && expr("3rd",1));
Finally a sensible answer in this thread. A corollary is: If you
want to use complex logical expressions, parenthise them so there
is NO DOUBT, NO DOUBT WHATSOEVER, what they mean. You will save a
lot of headaches, both your own and others.

(((((How) (would) (that) (help))?) (The (expressions (
((A || B) && C)
(and)
(A || (B && C))
) (have) ((the) (same) ((order) (of) (evaluation))).)
((There) (was) (never) ((any) (doubt) (about) (((the) (meaning))
(of) ((the) (expression)))))).
 
R

Robert Bachmann

Mark said:
What's next? When writing this do we need the comment shown?
idx++; /* Increment 'idx' */
just because it might confuse a beginner?
No. My point was that someone (a new code maintainer for example)
who reads code like "if (a & b)" can be in doubt that I really
wanted to bitwise-and "a" and "b".

I've often seen code like "if (a & b)" where the developer
actually should have written "if (a && b)".
So it always attracts my attention when I see code like "if (a & b)".
You, the developer must write the code you intend to write.
Yes, but nobody is perfect :)
Why should I not believe you meant bit-AND
if you write?
if (reg_a_bits & reg_a_field_mask)
If I would have written "if (reg_a_bits & reg_a_field_mask)"
it should be obvious to anyone that I really liked to bitwise-and
some bits with some mask.
In case "if (a & b)" it is not.
So picking up good (meaningful) variable names (as you already said)
is probably a better solution.

-rb
 
C

CBFalconer

Robert said:
When writing something like "if (a & b)" it is a good idea to
write "if (a & b) /*bitwise*/" instead.

On the other hand it looks a little bit funny to me, just like
some beginner who writes "int i; /*an integer variable*/" ;-)

So I for myself always use "if (a bitand b)" instead of
"if (a & b)" (after including <iso646.h> of course),
because with this notation it should be obvious to see that I
did *really* mean & and not &&.

I rarely use the ISO646 stuff, because it seems to bring out the
worst in diehard key savers. When I do, I would prefer to use
'and' for &&, and just & for the bitwise stuff. What I really
want out of ISO646 is and, or, xor, not. These make code much
more readable. They also help to enforce minimum intersymbol blank
standards.
 
C

CBFalconer

Old said:
(((((How) (would) (that) (help))?) (The (expressions (
((A || B) && C)
(and)
(A || (B && C))
) (have) ((the) (same) ((order) (of) (evaluation))).)
((There) (was) (never) ((any) (doubt) (about) (((the) (meaning))
(of) ((the) (expression)))))).

Not so.

A B Eval ((A || B) && C) Eval (A || (B && C))
== == =================== ====================
0 0 A B done=0 A B done=0
0 1 A B C done=C A B C done=C
1 0 A C done=C A B done=0
1 1 A C done=C A done=1

If I have made no mistakes. At any rate, the expression values
and side effects are different.
 
I

Irrwahn Grausewitz

CBFalconer said:
Old Wolf wrote:

Not so.

A B Eval ((A || B) && C) Eval (A || (B && C))
== == =================== ====================
0 0 A B done=0 A B done=0
0 1 A B C done=C A B C done=C
1 0 A C done=C A B done=0
^^^^^^^^^^
1 1 A C done=C A done=1

If I have made no mistakes.

Maybe it's me who is mistaken, but shouldn't the marked (^^^)
line read: A done=1 (just like the one below it)?
At any rate, the expression values
and side effects are different.

However, your claim is of course correct.

Regards
 
D

Dan Pop

In said:
When writing something like "if (a & b)" it is a good idea to
write "if (a & b) /*bitwise*/" instead.
On the other hand it looks a little bit funny to me, just like
some beginner who writes "int i; /*an integer variable*/" ;-)

The real solution is to write it as:

if ((a & b) != 0) ...

No silly comments needed to remove any doubt WRT your real intentions.
It is seldom a good idea to skip the explicit comparison.

Dan
 
P

pete

Dan said:
The real solution is to write it as:

if ((a & b) != 0) ...

No silly comments needed to remove any doubt WRT your real intentions.
It is seldom a good idea to skip the explicit comparison.

I believe that you're implying that it's a good idea
to skip the explicit comparison of the result of a logical operation.

You wouldn't write
if ((a && b) != 0)

right ?
 
D

Dan Pop

In said:
I believe that you're implying that it's a good idea
to skip the explicit comparison of the result of a logical operation.

You wouldn't write
if ((a && b) != 0)

right ?

Right. When dealing with a logical expression, the explicit comparison
of the result is pointless, because the intent is obvious. Ditto for
numeric variables that are used as flags (conceptually booleans), where
the intent is equally obvious. E.g. I would write:

int i, access_ok = 0;
...
if (i != 0) /* do this */ ;
if (access_ok) /* do that */ ;

Dan
 
P

pete

Dan said:
When dealing with a logical expression, the explicit comparison
of the result is pointless, because the intent is obvious. Ditto for
numeric variables that are used as flags (conceptually booleans),
where the intent is equally obvious. E.g. I would write:

int i, access_ok = 0;
...
if (i != 0) /* do this */ ;
if (access_ok) /* do that */ ;

Thank you.
 
C

Christopher Benson-Manica

Old Wolf said:
(((((How) (would) (that) (help))?) (The (expressions (
((A || B) && C)
(and)
(A || (B && C))
) (have) ((the) (same) ((order) (of) (evaluation))).)
((There) (was) (never) ((any) (doubt) (about) (((the) (meaning))
(of) ((the) (expression))))))

Was that intended to resemble (horrible) Lisp code? ;D
 

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
474,135
Messages
2,570,783
Members
47,341
Latest member
hanifree

Latest Threads

Top