Operator Precence Issue/Question

M

moogyd

Experts,

I have written (and delivered :-( ) some code. I wanted to check that
the bottom two bits of P8 were set, and so I produced:

if (P8 & (uint8)0x03 == (uint8)0x03) {
// Code
}

There is a mistake in this code in that equality is higher precedence
than bitwise and. Therefore my code behaves as:

if (P8 & ((uint8)0x03 == (uint8)0x03)) {
// Code
}

0x03==0x03 always equates to TRUE. Therefore my code equates to

if (P8 & TRUE) {
// code
}

So my question is, how is TRUE likely to be represented, and when will
the code be run.

(I fully expect the answer to be "It depends on the compiler")

Thanks

Steven (who usually uses the strongly typed VHDL)
 
R

Richard Heathfield

(e-mail address removed) said:
Experts,

I have written (and delivered :-( ) some code. I wanted to check that
the bottom two bits of P8 were set, and so I produced:

if (P8 & (uint8)0x03 == (uint8)0x03) {
// Code
}

Simplifying, without loss of generality: if(x & y == z)

Yes, it's a nasty one, that; dmr acknowledges that it was a mistake which
ought to have been fixed at an early stage. Too late now, of course.
There is a mistake in this code in that equality is higher precedence
than bitwise and. Therefore my code behaves as:

if (P8 & ((uint8)0x03 == (uint8)0x03)) {

Yes. More simply:

if(x & (y == z))
// Code
}

0x03==0x03 always equates to TRUE.

Well, it is either true or false. If it were false, it would yield 0. Since
it is true, it yields 1. (All conditional expressions behave in this way.)
Therefore my code equates to

if (P8 & TRUE) {
// code

More precisely, and using my generalisation:

if(x & 1)
}

So my question is, how is TRUE likely to be represented, and when will
the code be run.

The statement that succeeds the if() will be executed if the low bit of your
first value is set - i.e. if(x & 1) evaluates to 1.
(I fully expect the answer to be "It depends on the compiler")

For a mercy, it actually doesn't depend on the compiler on this occasion!
The operators == != < <= > >= always yield either 0 or 1 as their result,
and that is guaranteed by the Standard:


6.5.8 [...] Each of the operators < (less than), > (greater than),
<= (less than or equal to), and >= (greater than or equal
to) shall yield 1 if the specified relation is true and 0 if
it is false.80) The result has type int.

6.5.9 [...] Each of the operators yields 1 if the
specified relation is true and 0 if it is false. The result
has type int.
 
M

moogyd

Richard,

Thank you for the full and detailed response.

And as luck would have it, it's also the answer I wanted (by which I
mean I can work around without anyone knowing :) )

Steven



Richard said:
(e-mail address removed) said:
Experts,

I have written (and delivered :-( ) some code. I wanted to check that
the bottom two bits of P8 were set, and so I produced:

if (P8 & (uint8)0x03 == (uint8)0x03) {
// Code
}

Simplifying, without loss of generality: if(x & y == z)

Yes, it's a nasty one, that; dmr acknowledges that it was a mistake which
ought to have been fixed at an early stage. Too late now, of course.
There is a mistake in this code in that equality is higher precedence
than bitwise and. Therefore my code behaves as:

if (P8 & ((uint8)0x03 == (uint8)0x03)) {

Yes. More simply:

if(x & (y == z))
// Code
}

0x03==0x03 always equates to TRUE.

Well, it is either true or false. If it were false, it would yield 0. Since
it is true, it yields 1. (All conditional expressions behave in this way.)
Therefore my code equates to

if (P8 & TRUE) {
// code

More precisely, and using my generalisation:

if(x & 1)
}

So my question is, how is TRUE likely to be represented, and when will
the code be run.

The statement that succeeds the if() will be executed if the low bit of your
first value is set - i.e. if(x & 1) evaluates to 1.
(I fully expect the answer to be "It depends on the compiler")

For a mercy, it actually doesn't depend on the compiler on this occasion!
The operators == != < <= > >= always yield either 0 or 1 as their result,
and that is guaranteed by the Standard:


6.5.8 [...] Each of the operators < (less than), > (greater than),
<= (less than or equal to), and >= (greater than or equal
to) shall yield 1 if the specified relation is true and 0 if
it is false.80) The result has type int.

6.5.9 [...] Each of the operators yields 1 if the
specified relation is true and 0 if it is false. The result
has type int.

--
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)
 
S

santosh

Experts,

I have written (and delivered :-( ) some code. I wanted to check that
the bottom two bits of P8 were set, and so I produced:

if (P8 & (uint8)0x03 == (uint8)0x03) {
// Code
}

What is uint8? Standard C has no such type, but has uint8_t.
There is a mistake in this code in that equality is higher precedence
than bitwise and. Therefore my code behaves as:

if (P8 & ((uint8)0x03 == (uint8)0x03)) {
// Code
}

0x03==0x03 always equates to TRUE. Therefore my code equates to

if (P8 & TRUE) {
// code
}

So my question is, how is TRUE likely to be represented, and when will
the code be run.

In C, the relational operators always return 1 for true and 0 for
false, so in your case P8 would be bitwise and'ed with 0x01. So the IF
will evaluate to true if the Least Significant Bit of P8 is set, in
which case the statements inside the IF block will execute, otherwise
control will transfer to the statement after the IF block, (maybe an
ELSE?).
(I fully expect the answer to be "It depends on the compiler")

I don't know for sure, but I don't believe compilers will differ over
this. The Standard guarentees that relational expressions will yield
either 1 or 0, so conforming compilers, (compiling in a conforming
mode), should all behave the same.

Whether the IF evaluates true or not depends on the bit representation
of P8, (i.e. it's vaue), which only you know.
 
E

Eric Sosman

Experts,

I have written (and delivered :-( ) some code. I wanted to check that
the bottom two bits of P8 were set, and so I produced:

if (P8 & (uint8)0x03 == (uint8)0x03) {
// Code
}

There is a mistake in this code in that equality is higher precedence
than bitwise and. [...]

Some compilers and some "lint" programs will issue
warnings for perfectly valid C that likely doesn't mean
what was intended. Check the documentation for your
compiler and/or lint to see whether you can make them
more sensitive to this sort of thing, so as to avoid such
errors in the future.

Even if you ultimately use Frobozz Magic C to compile
your programs, it might be worth while to run additional
compilations with gcc, say, just for the diagnostics.
 
S

santosh

Eric said:
Experts,

I have written (and delivered :-( ) some code. I wanted to check that
the bottom two bits of P8 were set, and so I produced:

if (P8 & (uint8)0x03 == (uint8)0x03) {
// Code
}

There is a mistake in this code in that equality is higher precedence
than bitwise and. [...]

Some compilers and some "lint" programs will issue
warnings for perfectly valid C that likely doesn't mean
what was intended.
.... snip ...

By saying there is a mistake in his code, the OP is talking about a
semantic error on his part, not that the code was rejected by the
compiler, (since as you say, it's perfectly valid C).
 
E

Eric Sosman

santosh said:
Eric said:
Experts,

I have written (and delivered :-( ) some code. I wanted to check that
the bottom two bits of P8 were set, and so I produced:

if (P8 & (uint8)0x03 == (uint8)0x03) {
// Code
}

There is a mistake in this code in that equality is higher precedence
than bitwise and. [...]

Some compilers and some "lint" programs will issue
warnings for perfectly valid C that likely doesn't mean
what was intended.

... snip ...

By saying there is a mistake in his code, the OP is talking about a
semantic error on his part, not that the code was rejected by the
compiler, (since as you say, it's perfectly valid C).

Yes, and I'm also saying that some compilers will issue
warnings for "perfectly valid but quite possibly erroneous C."
Do you doubt this?

By encouraging his compilers and other tools to emit such
warnings and by paying attention to what they tell him, he
may be able to increase the likelihood that such semantic
errors will be caught before they become embarrassing.
 
S

santosh

.... snip ...
There is a mistake in this code in that equality is higher precedence
than bitwise and. [...]

Some compilers and some "lint" programs will issue
warnings for perfectly valid C that likely doesn't mean
what was intended.

... snip ...

By saying there is a mistake in his code, the OP is talking about a
semantic error on his part, not that the code was rejected by the
compiler, (since as you say, it's perfectly valid C).

Yes, and I'm also saying that some compilers will issue
warnings for "perfectly valid but quite possibly erroneous C."
Do you doubt this?

No. I failed to grasp what you meant the first time around. I
understand now, though, in my limited experience, I've yet come across
a compiler that smart, but then again, I've only used about five
different compilers. I've found splint to be more suited for this.
By encouraging his compilers and other tools to emit such
warnings and by paying attention to what they tell him, he
may be able to increase the likelihood that such semantic
errors will be caught before they become embarrassing.

Absolutely, though these tools should not be a replacement for a C
textbook.
 
E

Eric Sosman

santosh said:
No. I failed to grasp what you meant the first time around. I
understand now, though, in my limited experience, I've yet come across
a compiler that smart, but then again, I've only used about five
different compilers. I've found splint to be more suited for this.

You should make a point of becoming acquainted with gcc.
Many things good and bad can be and have been said of it, but
IMHO it has the best diagnostics of any compiler I've encountered.
(If properly propitiated, of course: "-Wall -W -ansi -pedantic"
is a good starting point, possibly with "-std=something_else"
instead of "-ansi".)
 
A

Andrew Poelstra

You should make a point of becoming acquainted with gcc.
Many things good and bad can be and have been said of it, but
IMHO it has the best diagnostics of any compiler I've encountered.
(If properly propitiated, of course: "-Wall -W -ansi -pedantic"
is a good starting point, possibly with "-std=something_else"
instead of "-ansi".)

Agreed.

For example, I once used the construct (ch[1] == ch[2] == '-') to check
for a comment in an XML document (it was already known that ch[0] was '<').
I likely would have had a very difficult time noticing that bug on my own,
because the construct "a = b = c" /is/ correct. (This is an interesting
variant on the =/== typo that isn't mentioned in any books I've read).

Anyway, gcc gave me the following message (paraphrased):
warning: expressions of the form (a <= b <= c) do not have their
mathematical meaning.

and saved me several potential hours of debugging.
 
S

santosh

Eric said:
You should make a point of becoming acquainted with gcc.

Though gcc is what I use 90 % of the time, I haven't really explored
it's options in depth. I really should though.
Many things good and bad can be and have been said of it, but
IMHO it has the best diagnostics of any compiler I've encountered.

I agree and I would probably place Borland's compiler second in this
regard.
(If properly propitiated, of course: "-Wall -W -ansi -pedantic"
is a good starting point, possibly with "-std=something_else"
instead of "-ansi".)

Exactly what I use for all my programs, (with std=c99 for the
ocassional one that needs it). Recently I've started trying the
exhaustive set of diagnostics switches Richard Heathfield posted. It's
made me reconsider quite a number of constructs, (plus the excellent
knowledge of this group of course).
 
K

Keith Thompson

Richard Heathfield said:
(e-mail address removed) said: [...]
0x03==0x03 always equates to TRUE.

Well, it is either true or false. If it were false, it would yield 0. Since
it is true, it yields 1. (All conditional expressions behave in this way.)

More precisely, all conditional *operators* behave in this way. The
language guarantees that the relational, equality, "&&", "||", and "!"
operators yield 1 for true and 0 for false. Other things that you
might think of as conditional expressions (e.g., a call to isdigit())
don't have this guarantee.
 
L

lovecreatesbeauty

I have written (and delivered :-( ) some code. I wanted to check that
the bottom two bits of P8 were set, and so I produced:

if (P8 & (uint8)0x03 == (uint8)0x03) {
// Code
}

There is a mistake in this code in that equality is higher precedence
than bitwise and. Therefore my code behaves as:

if (P8 & ((uint8)0x03 == (uint8)0x03)) {
// Code
}

0x03==0x03 always equates to TRUE. Therefore my code equates to

if (P8 & TRUE) {
// code
}

So my question is, how is TRUE likely to be represented, and when will
the code be run.

(I fully expect the answer to be "It depends on the compiler")

Is following the lines of code what you want,

int l2bs(int i)
{
const unsigned char MASK = 0x03; /*0000 0011*/
if ((i & MASK) == MASK)
i = 1; /*last 2 bits are set*/
else
i = 0; /*last 2 bits are not set*/
return i;
}

lovecreatesbeauty
 
M

moogyd

All,

Thanks for the advice and observations.

I will certainly look into the pendantic warnings options within GCC to
try an catch this type bug in future.

Steven
 
A

Andrew Poelstra

Is following the lines of code what you want,

int l2bs(int i)
{
const unsigned char MASK = 0x03; /*0000 0011*/
if ((i & MASK) == MASK)
i = 1; /*last 2 bits are set*/
else
i = 0; /*last 2 bits are not set*/
return i;
}

That function could be replaced with

int l2bs (int i)
{
return (i & 0x03) == 0x03
}

Or a macro:
#define #L2BS(n) ((n) & 3 == 3)
 

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,181
Messages
2,570,970
Members
47,537
Latest member
BellCorone

Latest Threads

Top