The Question:
Does doing if(SomeFunction() == TRUE)
instead of doing if(SomeFunction())
protect against some type of coding error? I'm trying to understand if this is protecting from some hidden land-mine, or if it's the result of someone writing code who didn't quite understand how expressions are evaluated. I understand that if done right, both of these things evaluate the same. Just like if(value == 42)
and if(42 == value)
evaluate the same - still, some prefer the 2nd version because it produces a compiler error if someone typo's the == and writes = instead.
Background: I've inherited some embedded software that was written 4 or 5 years ago by people who don't work here anymore. I'm in the middle of some refactoring to get rid of multi-hundred line functions and global variables and all that jazz, so this thing is readable and we can maintain it going forward. The code is c for a pic microprocessor. This may or may not be relevant. The code has all sorts of weird stuff in it that screams "didn't know what they were doing" but there's a particular pattern (anti-pattern?) in here that I'm trying to understand whether or not there's a good reason for
The Pattern: There are a lot of if statements in here that take the form
if(SomeFunction() == TRUE){
. . .
}
Where SomeFunction() is defined as
BOOLEAN SomeFunction(void){
. . .
if(value == 3)
return(FALSE);
else
return(TRUE);
}
Let's ignore the weird way that SomeFunction returns TRUE or FALSE from the body of an if statement, and the weird way that they made 'return' look like a function invocation.
It seems like this breaks the normal values that c considers 'true' and 'false' Like, they really want to make sure the value returned is equal to whatever is defined as TRUE. It's almost like they're making three states - TRUE, FALSE, and 'something else' And they don't want the 'if' statement to be taken if 'something else' is returned.
My gut feeling is that this is a weird anti-pattern but I want to give these guys the benefit of the doubt. For example I recognize that if(31 == variable)
looks a little strange but it's written that way so if you typo the == you don't accidently assign 31 to variable. Were the guys that wrote this protecting against a similar problem, or is this just nonsense.
Additional Info
- When I wrote this question, I was under the impression that stdbool was not available, but I see now that it's provided by the IDE, just not used in this project. This tilts me more towards "No good reason for doing this."
- It looks like BOOLEAN is defined as
typedef enum _BOOLEAN { FALSE = 0, TRUE } BOOLEAN;
- The development environment in question here is MPLAB 8.6
TRUE
is zero, then yes! Otherwise, not really. It might sound nice to have operations independent of the actual values of booleans, but in practice it’s just messy, as you say. – Mailemailedif(SomeFunction() == TRUE)
has limited value, likeint SomeFunction()
returns 3 or more values and codes need to test if the return value wasTRUE
– Kazmircitrue
(not always1
). In C0
is false and anything else is true.int apples = 3; if(apples) {...}
– Rettarettigand the weird way that they made 'return' look like a function invocation
What do you mean? Also, it s/breturn (3 == value) ? 0 : 1;
– Everybodyreturn 3 != value;
– Rettarettigreturn
statement does not require parentheses around the expression. The parentheses are not incorrect (it's just a parenthesized expression), but they're unnecessary and potentially obfuscating.return(42);
looks very similar to a function call;return 42;
clearly is a return statement. And a pre-C99 compiler will flagretrun 42;
but is likely to compileretrun(42);
without complaint, resulting in a link-time error. – NancynandorSomeFunction()
returns some non-zero value other then whatever TRUE is defined as; in which case it will also fail. – Yaekoyaeltrue
rather thenTRUE
, while elsewhere your refer to TRUE. If stdbool.h is included,true
is defined and has type_Bool
(with a typedef aliasbool
) and is a genuine boolean type. You may even get a warning if you attempt to compare it to an int or enum or whateverBOOLEAN
is defined as. – Yaekoyaelbool
andtrue
throughout. The problem with defining a boolean alias is that everyone does it perhaps slightly differently using different base types such as int, char or an enum for example, declared using macros or typedef, but often using the same or similar symbol names which makes using code from multiple sources a real pain when every vendor thought it was a good idea to define a boolean type. Not only is the idiom in question a bad idea, defining BOOLEAN is too – Yaekoyaelif(SomeFunction() == TRUE)
is good style is simply wrong. Some people will tell you that the explicit== TRUE
is important for some reason or other. You can't convince them otherwise, so just ignore them. – Lindbom<stdbool.h>
is not included,true
could be anything. (Not relevant here, since the code usesTRUE
.) – Nancynandor_BOOLEAN
causes undefined behavior. Identifiers starting with two underscores, or with an underscore and an uppercase letter, are reserved to the implementation. Rather thantypedef enum _BOOLEAN { FALSE = 0, TRUE } BOOLEAN;
, it could be justtypedef enum { FALSE, TRUE } BOOLEAN;
– Nancynandortrue
, so veryTRUE
. :-) – Kazmirciif(function() == TRUE)
?" which will have pros and cons. The reasons for the "con" apply to why this style of code should not have been used in the first place. – KazmirciBOOLEAN f()
returns something other thanFALSE
,TRUE
(After all its only an enumerated type) you are S.O.L.. Ifsizeof(_Bool) != sizeof(BOOLEAN)
, oralignof(_Bool) != alignof(BOOLEAN)
you get to lose even more sleep. I do not think the rank will be a concern, but you might want to check if both promote toint
. And I hope no code usesBOOLEAN
as a bit field. – KazmirciBOOLEAN
,TRUE
andFALSE
, vrify they are identically use like the standard type/macros and replace them if they are. This might be done by a simple search/replace or refactoring tool. Next phase is to modify the useless comparisons withTRUE
/FALSE
. Then simplify where the values are generated. All presuming you have the time and your bosses won't cancel the rework mid-term (all seen). – Anjanetteif (IsUSBConfigured() != FALSE)
?? – Nearly