Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this condition always true? (pktNum != invPktNum)

Tags:

c

When I compile the following code, my compiler complains that the following line is always true. I think I may have a faulty understanding of the != operator...

if (pktNum != ~invPktNum) {
    return 1;
}

I'm trying to verify that invPktNum is indeed the inverse of pktNum. If not, exit immediately, otherwise proceed as normal.

I've checked and pktNum an unsigned char that is 0x01 and invPktNum is an unsigned char that is 0xFE at the time of comparison.

Can anybody enlighten me? Thanks in advance!

like image 835
Justin Avatar asked Nov 22 '10 23:11

Justin


1 Answers

In C, values in most expressions that are of a type narrower than int are promoted to a wider type before the calculation takes place. If int is wide enough to hold all the values of the narrower type, then it is promoted to int; otherwise it is promoted to unsigned int.

In this case, int is wide enough to hold all the values of your unsigned char, so your values are promoted to int.

pktNum (and thus, the promoted pktNum) can have a value between 0 and 255 inclusive. This is the value that will be used on the left hand side of the != operator.

invPktNum can likewise have a value between 0 and 255 inclusive. This value will be promoted to int, and then bitwise-negated. The result of this bitwise negation will always be a negative number, since the sign bit will be negated. This is the value that will be used on the right hand side of the != operator.

No negative number can ever be equal to the promoted pktNum, so the condition is always true.

To perform the calculation that you actually want to, you need to mask out the lower eight bits after the negation:

if (pktNum != (~invPktNum & 0xff)) {
    return 1;
}

Or alternatively, you can just negate the bits you're interested in:

if (pktNum != (invPktNum ^ 0xff)) {
    return 1;
}
like image 144
caf Avatar answered Oct 03 '22 04:10

caf