Paraense
Paraense

Reputation: 53

Can this C/C++ if() statement ever evaluate to TRUE?

According to PC-lint, the following statement will never be TRUE:

if((variable & 0x02) == 1)

I am using a C compiler for embedded systems that evaluates it to TRUE whenever the corresponding bit in variable is set. I guess the compiler is doing a TRUE/FALSE comparison of both sides of the == instead of comparing the resulting numbers. In other words, every time the expression (varable & 0x02) is not zero (i.e. TRUE), the statement will also be TRUE, since the value 1 is also TRUE (not zero).

I don't know if the C/C++ standards clearly define how a compiler should behave in this case. Are there any C/C++ experts out there who can answer this question based on what the standards (e.g. C90, C99, etc.) say?

P.S.: In the statement above, "variable" is an unsigned char.

Upvotes: 5

Views: 1758

Answers (6)

NPE
NPE

Reputation: 500407

PC-lint is right. Assuming var is an integer variable, the expression var & 0x02 can evaluate to two values: 0 and 2. It will never be equal to 1, which is what the if statement is testing.

To expand on this, the equality operator is being applied to two integer values. What matters is whether both operands evaluate to the same number, not whether they're both simultaneously "true" or "false".

To test whether bit 1 is set, one could use:

if (variable & 0x02) {
  ...
}

Given that your compiler behaves the way you say it does, it's clearly non-compliant. However, it will almost certainly handle if (variable & 0x02) correctly. My recommendation would be to fix the code so it won't break silently if you were ever to change compilers.

Finally, the situation is different if: (1) the code is C++ and not C; and (2) variable is instance of a class; and (3) the class overloads the operators in question. In that case, the behaviour is down to what the overloaded operators actually do.

Upvotes: 11

undur_gongor
undur_gongor

Reputation: 15954

For C, the answer is no.

The C standard says about & (6.5.10):

The result of the binary & operator is the bitwise AND of the operands (that is, each bit in the result is set if and only if each of the corresponding bits in the converted operands is set).

Since in 2 only the bit 1 is set, the value of the expression can only have set the bit 1. It can take no other values than 2 and 0. Neither 2 nor 0 can compare equal to 1.

The bit representations of integers are defined in 6.2.6.2 (for non-negative values in the usual way).

Upvotes: 1

niko
niko

Reputation: 9393

Let us consider the binary value of 2

  02 = 0010 (say a 4 bit number)

and the binary value of 1 is

  01 = 0001 

The least significat bit of 2 is always zero that is the left most bit is 0. SO
The & (and) operation with 0 never gives 1 hence we can say it can never be equal to 1

      0 0 =>    0
      0 1 =>    0
      1 1 =>    1 

Note: & indicates the bit wise and operation

   2 - 0010
   3 - 0011
       0010

So the output with xx & 2 will be 0 or 2.

Upvotes: 0

bdonlan
bdonlan

Reputation: 231193

In C++, this can evaluate to a true value if (and only if) variable is an instance of a class with an overloaded operator& which does not conform to normal bitwise AND semantics.

In C, this condition will always be false. §6.5.10 defines the semantics of the bitwise AND operator, and it's quite simple and to the point:

 4. The result of the binary & operator is the bitwise AND of the operands (that is, each bit in the result is set if and only if each of the corresponding bits in the converted operands is set).

It's clear that the result cannot be 1, as the 1 bit is not set in the converted value of the right-hand-side operand (namely, 0x02).

Naturally, if undefined behavior has been invoked at some point in the program's past (or at compile time!), then anything can happen. Barring this possibility, however, your compiler is non-compliant. That is to say, broken. This, unfortunately, is extremely common on odd embedded compilers. If you're lucky, you may even be able to report the bug and get it fixed.

Upvotes: 6

Dirk
Dirk

Reputation: 31053

Basically, lint is right here. At least on any platform I know of, the condition will yield false. Look at the bit representation of the numbers: x & 2 (0010) will always be either zero or 2 (0010) and thus different from 1 (0001) for any integer x.

Upvotes: 0

m0skit0
m0skit0

Reputation: 25873

I don't think the standard defines anything about this very specific and unusual issue. As said by aix, that statement can never be true because (in binary):

XXXX XXXX -> variable
0000 0010 -> 0x02
--------- AND
0000 00X0 -> result

(simplifying to 8-bit types)

So your only results can be 0000 0010 (which is 2) or 0000 0000 (which is 0).

Upvotes: 4

Related Questions