Fundamentals of Logic
-
We had to modify some existing code inherited from another party and had some false positive error detection. The root cause:
#define FALSE (0xFA45U) #define TRUE (0x55AAU)
Yes, this is embedded code, but when FALSE != ~TRUE I don't know how to interpret the universe.
-
P.S. Yes, what got us is we had code like:
void our_new_function(boolean bFlag)
{
if(bFlag)
{
// do stuff if flag is true
}
else
{
// do stuff if flag is false
}
}
void function_from_old_supplier()
{
boolean bFlag;
bFlag = FALSE;
if(some_condition)
{
bFlag = TRUE;
}
our_new_function(bFlag); // New function call using bFlag status}
-
I suppose this was an attempt to weed out the type of code posted above? Defining FALSE and TRUE this way would enforce all C code to explicitly say if (foo==FALSE), etc.
I would almost be fine with this if FALSE and TRUE were lowercase instead :)
-
@too_many_usernames said:
I think you mean FALSE != !TRUE. The common definitions:Yes, this is embedded code, but when FALSE != ~TRUE I don't know how to interpret the universe.
#define FALSE 0
#define TRUE !FALSEWill result in:
TRUE = 1
FALSE = 0
~TRUE = -2
-
@joeyadams said:
I suppose this was an attempt to weed out the type of code posted above? Defining FALSE and TRUE this way would enforce all C code to explicitly say if (foo==FALSE), etc.
I would almost be fine with this if FALSE and TRUE were lowercase instead :)
I hate when people say that I should write code like this:
if (myBool == TRUE) { /* blah */ }
instead of
if (myBool) { /*blah*/ }
-
@joeyadams said:
I suppose this was an attempt to weed out the type of code posted above? Defining FALSE and TRUE this way would enforce all C code to explicitly say if (foo==FALSE), etc.
I would almost be fine with this if FALSE and TRUE were lowercase instead :)
Sadly, it was more an attempt to avoid bit corruption in an embedded application ... which already has fault-tolerante ECC memory, checksums, and watchdogs because defining any value as TRUE or FALSE will not save you from bit corruption anyway. Instead they made it more likely for mistakes that cannot be caught by a static checker because everyone expects if ( bool ) to work as expected without having to do the silly
if ( bool == TRUE) { // stuff if TRUE } else if (bool == FALSE) { // stuff if FALSE } else { // stuff if FILE_NOT_FOUND or other nonsense }
which is what you'd really have to do to be 'safe' in this case.
-
@tdb said:
I think you mean FALSE != !TRUE. The common definitions:
#define FALSE 0
#define TRUE !FALSEWill result in:
TRUE = 1
FALSE = 0
~TRUE = -2Essentially what you're saying is, if you expand a boolean value into a quantity that can have more than two states, you have to be careful.
I agree with that =)
(I would probably argue that the best implementation is FALSE = ~TRUE = !TRUE which means the only allowed values would be 0 and ~0)
-
I hate when people say that I should write code like this:
if (myBool == TRUE) { /* blah */ }
instead of
if (myBool) { /*blah*/ }
Who would say that?
Obviously you should write it like:
if (TRUE == myBool) { /* blah */ }
Admittedly, this is a tongue in cheek response, and I think it's silly also, however people say the constant should come first to avoid =/== issues.
-
@Lacutis said:
I hate when people say that I should write code like this:
if (myBool == TRUE) { /* blah */ }
instead of
if (myBool) { /*blah*/ }
Who would say that?
Obviously you should write it like:
if (TRUE == myBool) { /* blah */ }
Admittedly, this is a tongue in cheek response, and I think it's silly also, however people say the constant should come first to avoid =/== issues.Actually, to be on the safe side, you should do:
if (TRUE > myBool || TRUE < myBool) { /* blah */ }
But if == is overloaded, that could be a problem. Perhaps the best way is this:
#if defined(__cplusplus) || defined(c_plusplus)
if (TRUE == myBool || myBool == TRUE) { /* blah */ }
#else
if (TRUE > myBool || TRUE < myBool) { /* blah */ }
#endif
Of course, this is super-tongue-in-cheek. I personally prefer:
#if FALSE!=0 || TRUE!=1
#error "WTF?!"
#endif