Reputation: 3742
I am maintaining a legacy c code which contain unknown logic to me. Obviously it has something to do with the bitwise operation of unsigned char. However I am not familar with the bitwise operation, could anyone be kind and explain the mechanism behind this? I included some key statements.
private const unsigned char DONE_HDR = 0x01;
private const unsigned char DONE_TRL = 0x02;
private const unsigned char DONE_ACC = 0x04;
private const unsigned char DONE_NTW = 0x08;
unsigned char done = 0;
What is it assigning to the variables? 16 bit number?
case TAP_HDR:
if (done & DONE_HDR){
//do something
}
done |= DONE_HDR;
break;
case TAP_TRL:
if (done & DONE_TRL){
//do something
}
done |= DONE_TRL;
break;
case TAP_ACC:
if (done & DONE_ACC){
//do something
}
done |= DONE_ACC;
break;
case TAP_NTW:
if (done & DONE_NTW){
//do something
}
done |= DONE_NTW;
break;
How can unsigned char be evaluated? I thought we can only evaluate boolean or number. And if the number if positive, it will be evaluated to be true. However unsigned char has no negative value so I am puzzled here. When will it be true? And what is the purpose/result of the "&" operation?
And if after that, no matter if the above if statement evaluated to be true, it goes:
done |= DONE_HDR;
Seems to be recording the status. I guess whatever comes out of it must depends on the value of "done" because DONE_HDR is a constant.
Finally it check:
if (!(done & DONE_HDR))
if (!(done & DONE_TRL))
if (!(done & DONE_ACC))
if (!(done & DONE_NTW))
Could be checking if it has encounter all the record. Once again, I don't know how does & play a role in here.
Upvotes: 0
Views: 1690
Reputation: 12711
In C every integer besides 0 is considered true while 0 is false.
Also a char is considered to be both a ASCII character as well as its numeric value.
The & operator does a bitwise AND, which means that one is comparing on a bit by bit basis, for example 0x01 will combine with 0x01 to give a results of 0x01, and 0x01 & 0x03 will resiult in 0x01 while 0x01 & 0x02 will give 0x00.
This can be illustrated:
0x01 is in bits: 00000001
0x03 in bits: 00000011
0x01& 0x03: 00000001
0x01: 00000001
0x02: 00000010
0x01 & 0x02: 00000000
A similar case is with | which is the bitwise OR operator, which means that it is doing an OR based on the underlying bits which means that 0x01 | 0x02 results in 0x03, because
0x01: 00000001
0x02: 00000010
0x01 | 0x03: 00000011
Contrast these with the && and || which are doing logical comparisons only, which in C means essentially that 0x01 and 0x02 are converted to true and then compared which results in true.
Also note that bitwise operators don't short circuit while the logical do, the reason is that for bitwise we need to compare the entire value, while for a logical comparison one value might suffice to know the result.
I haven't encountered the |= operator, but I guess it us a shorthand for done = done | MASK; Which essentialy results that the bit that is 1 in MASK will be set to 1 in done.
(Note for readers familiar with VB: most VB programmers are probably unaware, but the VB keyword AND\OR\NOT is in fact a bitwise AND, there is no logical AND in VB6 but in VB.Net there is the AndAlso operator, and as a result (1 And 2) is actually false in VB because it is bitwise, and this is also the reason why in VB there is no short circuit evaluation, this can also have an effect when dealing with the Win32API, since doing NOT on a API function that returns 1 is in effect -1 which is also true, and not a logical NOT.)
Upvotes: 2
Reputation: 1
First, private
is not a C keyword. I guess some header #define
-s it to some attribute or other compiler specific extension (or maybe to static
)
On almost all C implementations, a char
or unsigned char
is one byte (of 8 bits). The plain char
type may be signed or unsigned (this important choice is implementation dependent and usually architecture specific; on some compilers like GCC it can be configured thru compiler options). An unsigned char is usually an unsigned byte (with values from 0 to 0xff). A signed char is usually a signed byte (from -128 to +127).
The names DONE_HDR
et al are defined as const
so an optimizing compiler could constant-fold them.
Your code is just testing bit fields in done
(using e.g. done & DONE_HDR
) and updating that variable (setting that bit with done |= DONE_HDR
).
Upvotes: 3
Reputation: 224844
&
is the bitwise AND operator. So the expressions like:
(done & MASK)
Are checking to see if the MASK
bit is set in done
. That means:
!(done & MASK)
Is checking to see if MASK
is cleared. The assignment operator lines:
done |= MASK;
Is setting the MASK
bit in done
.
char
and signed char
and unsigned char
are integer types pretty much just like any other integer types - they're just normally smaller. Most often they're 8-bit types, but you can check the CHAR_BIT
macro in stdint.h
to be sure.
Upvotes: 4