Is comparing a BOOL against YES dangerous? - objective-c

I found a comment today in a source file:
// - no longer compare BOOL against YES (dangerous!)
Is comparing BOOL against YES in Objective-C really that dangerous? And why is that?
Can the value of YES change during runtime? Maybe NO is always 0 but YES can be 1, 2 or 3 - depending on runtime, compiler, your linked frameworks?

The problem is that BOOL is not a native type, but a typedef:
typedef signed char BOOL;
#define YES (BOOL)1
#define NO (BOOL)0
As a char, its values aren't constrained to TRUE and FALSE. What happens with another value?
BOOL b = 42;
if (b)
{
// true
}
if (b != YES)
{
// also true
}

You should never compare booleans against anything in any of the C based languages. The right way to do it is to use either:
if (b)
or:
if (!b)
This makes your code much more readable (especially if you're using intelligently named variables and functions like isPrime(n) or childThreadHasFinished) and safe. The reason something like:
if (b == TRUE)
is not so safe is that there are actually a large number of values of b which will evaluate to true, and TRUE is only one of them.
Consider the following:
#define FALSE 0
#define TRUE 1
int flag = 7;
if (flag) printf ("number 1\n");
if (flag == TRUE) printf ("number 2\n");
You should get both those lines printed out if it were working as expected but you only get the first. That's because 7 is actually true if treated correctly (0 is false, everything else is true) but the explicit test for equality evaluates to false.
Update:
In response to your comment that you thought there'd be more to it than coder stupidity: yes, there is (but I still wouldn't discount coder stupidity as a good enough reason - defensive programming is always a good idea).
I also mentioned readability, which is rather high on my list of desirable features in code.
A condition should either be a comparison between objects or a flag (including boolean return values):
if (a == b) ...
if (c > d) ...
if (strcmp (e, "Urk") == 0) ...
if (isFinished) ...
if (userPressedEsc (ch)) ...
If you use (what I consider) an abomination like:
if (isFinished == TRUE) ...
where do you stop:
if (isFinished == TRUE) ...
if ((isFinished == TRUE) == TRUE) ...
if (((isFinished == TRUE) == TRUE) == TRUE) ...
and so on.
The right way to do it for readability is to just use appropriately named flag variables.

All this is true, but there are valid counter arguments that might be considered:
— Maybe we want to check a BOOL is actually YES or NO. Really, storing any other value than 0 or 1 in a BOOL is pretty incorrect. If it happens, isn't it more likely because of a bug somewhere else in the codebase, and isn't not explicitly checking against YES just masking this bug? I think this is way more likely than a sloppy programmer using BOOL in a non-standard way. So, I think I'd want my tests to fail if my BOOL isn't YES when I'm looking for truth.
— I don't necessarily agree that "if (isWhatever)" is more readable especially when evaluating long, but otherwise readable, function calls,
e.g. compare
if ([myObj doThisBigThingWithName:#"Name" andDate:[NSDate now]]) {}
with:
if (![myObj doThisBigThingWithName:#"Name" andDate:[NSDate now]]) {}
The first is comparing against true, the second against false and it's hard to tell the difference when quickly reading code, right?
Compare this to:
if ([myObj doThisBigThingWithName:#"Name" andDate:[NSDate now]] == YES) {}
and
if ([myObj doThisBigThingWithName:#"Name" andDate:[NSDate now]] == NO) {}
…and isn't it much more readable?
Again, I'm not saying one way is correct and the other's wrong, but there are some counterpoints.

When the code uses a BOOL variable, it is supposed to use such variable as a boolean. The compiler doesn't check if a BOOL variable gets a different value, in the same way the compiler doesn't check if you initialize a variable passed to a method with a value taken between a set of constants.

Related

Why generate YES and NO via conditional operator vs. using condition directly?

In Cocoa's NSRange.h, I noticed the following inline function:
NS_INLINE BOOL NSLocationInRange(NSUInteger loc, NSRange range) {
return (!(loc < range.location) && (loc - range.location) < range.length) ? YES : NO;
}
I found it rather perplexing that the author chose to return YES and NO via a conditional operator instead of writing the function like:
NS_INLINE BOOL NSLocationInRange(NSUInteger loc, NSRange range) {
return (!(loc < range.location) && (loc - range.location) < range.length);
}
Is there any reason why the former is preferable? I normally would consider this to just be a quirky programming style, but wondered (possibly erroneously) if there was something I'm missing since it's in one of Apple's public .h files...
It is just poor programming style/understanding. Don't do it.
It is often seen in the work of students who don't properly understand that booleans are values (as they are not numbers and they equate values with numbers) and expressions can be boolean valued.
Note: The boolean/logical operators in (Objective-)C(++) are defined to return integers rather than booleans, so some confusion over booleans is understandable in these languages. However the integers are either 0 or 1 and correspond to false/NO & true/YES respectively.

Why use double parentheses in init methods, or is 1 == (1)?

What do parentheses do when evaluating some meaning?
I have faced this in code, when something is checked and they use
if ( (some condition that returns 1) )
{
code
}
So my question is, does this evaluate to true? I would think that it is always false since (1) does not return anything?
Edit: clarification, question is why double parenthesis in if? I know that 1 is true.
The additional parentheses are used when an assignment is used for its truth value. They allow the compiler to distinguish between
if ((var = expr))
which signals intentional combination of assignment and truth value test, and
if (var = expr)
as an unintentional misspelling of if (var == expr).
The convention, carried over from C and C++, is for the compilers to warn on if (var = expr) as a possible misspelling of if (var == expr). They don't warn on if ((var = expr)), because the extra set of parentheses signals to the compiler that the assignment was intended. As rob mayoff explains, clang has a special case not to warn for certain assignments to self, but for many coders the habit remained.
As others said, the generated code is exactly the same with and without the extra parens.
If you write,
if (self = [super init]) { // Warning
// ...
}
The compiler will give you a warning, because it thinks you might have mistyped = as ==. If you add a second set of parentheses, the warning goes away.
if ((self = [super init])) { // No warning
// ...
}
So the extra parentheses are there to make typos less likely. The parentheses do not change the value of the expression.
In general 0 equates to false, NOT 0 to true.
This link explains bool in objective-c: http://www.mindsizzlers.com/2010/04/objective-c-and-the-properties-of-bool/
true and false value of bool and int
boolean value of false is equivalent to the int value of 0.
boolean value of true is equivalent to the int value of non-zero (e.g. 1, 10, 3000, etc)
For example, consider an example of C code below:
bool bValue;
int nValue;
bValue = true;
nValue = 1;
if (bValue == nValue) {
printf("bValue and nValue are the same!\n");
}
// output: bValue and nValue are the same!
Wrapped with multiple parenthesis:
The following two snippets returns exactly the same results.
if ((((((((((((((((((((1)))))))))))))))))))) {
printf("Hello World!\n");
}
returns the same result as:
if (1) {
printf("Hello World!\n");
}
Expression in if statement
Within your given if statement, you must have an expression that resolves to either true or false value. Please refer to this page for example of expression.

How can casting pointer to BOOL return 112?

Let's say I have a pointer to some object, called myObject, and I need to know, whether it is really pointing to something. How can this code:
// assume MyObjectClass *myObject;
return (BOOL)myObject;
return 112? I know, that I can always write
return (myObject == nil);
and everything will be fine. But until today I have always assumed, that explicit casting of anything to bool will always return true or false (as far as I know, 0 is always considered as false and any other value as true) and that BOOL with it's YES and NO values is just "renamed" bool. So basically, my questions are:
Why is it returning 112? :-)
Are results of explicit casting defined somewhere in C/Objective-C standard, or is it compiler-specific?
In Objective-C, the BOOL macro is just a typedef for signed char with YES/NO defined, but bool is an actual boolean, which can be true or false.
It returns 112, because it rounds the address of your pointer to signed char type.
Here is some discussion with good answers:
Objective-C : BOOL vs bool
Is there a difference between YES/NO,TRUE/FALSE and true/false in objective-c?
The definition of "true" in C is any non-zero number. Therefore 112 would be considered true as far as C is concerned. From the C99 standard:
6.3.1.2 Boolean type
When any scalar value is converted to _Bool, the result is 0 if the value compares equal
to 0; otherwise, the result is 1.
Your value is not converted to 1 because you are converting to BOOL not _Bool. The conversion to 0/1 will be technically handled inside the if (though in reality the implementation is more likely to be (myObject != 0) inside any if/while type statement).
In C , bool is a stdbool.h macro for boolean type _Bool.
And a conversion of a non-zero integer value to _Bool is guaranteed to yield 1.
That is, the result of 1 == (bool) 42 is 1.
If you are using a BOOL type as an alias for another integer type (like signed char), you can get a different result:
The result of 1 == (BOOL) 42 is 0.

Shorthand for all bools YES or all bools NO?

Often in my code I need to check whether the state of x amount of bools are all true OR all bools are false. So I do:
BOOL first, second, third;
if((first && second && third) || (!first && !second && !third))
//do something
Being a lazy programmer, I want to know if there is some mathematical shorthand for this kind of query, instead of having to type out this whole thing every time?
The shorthand for all bools the same is testing for (pairwise) equality:
(first==second && second==third)
Of course you can expand this to any number of booleans, having N-1 equality checks joined with the and operator.
If this is something you frequently require then you're better off using an integer and reading bits individually.
For instance, instead of:
BOOL x; // not this
BOOL y; // not this
BOOL z; // not this
...and instead of bit fields (because their layout is implementation-defined):
unsigned int x : 1; // not this
unsigned int y : 1; // not this
unsigned int z : 1; // not this
...use a single field such as:
unsigned int flags; // do this
...and assign every value to a bit; for example:
enum { // do this
FLAG_X = (1 << 0),
FLAG_Y = (1 << 1),
FLAG_Z = (1 << 2),
ALL_FLAGS = 0x07 // "all bits are on"
};
Then, to test "all false" you simply say "if (!flags)" and to test "all true" you simply say "if (flags == ALL_FLAGS)" where ALL_FLAGS is a number that sets all valid bits to 1. Other bitwise operators can be used to set or test individual bits as needed.
Note that this technique has an upper limit of 32 Boolean values before you have to do more (e.g. create an additional integer field to store more bits).
Check if the sum is 0 or equal to the number of bools:
((first + second + third) % 3 == 0)
This works for any number of arguments.
(But don't take this answer serious and do it for real.)
When speaking about predicates, you can usually simplify the logic by using two variables for the quantification operations - universal quantification (for all) and existential quantification (there exists).
BOOL allValues = (value1 && value2 && value3);
BOOL anyValue = (value1 || value2 || value3);
if (allValues || !anyValue) {
... do something
}
This would also work if you have a lot of boolean values in an array - you could create a for cycle evaluating the two variables.

Does "if ([bool] == true)" require one more step than "if ([bool])"?

This is a purely pedantic question, to sate my own curiosity.
I tend to go with the latter option in the question (so: if (boolCheck) { ... }), while a coworker always writes the former (if (boolCheck == true) { ... }). I always kind of teased him about it, and he always explained it as an old habit from when he was first starting programming.
But it just occurred to me today that actually writing out the whole == true part may in fact require an additional step for processing, since any expression with a == operator gets evaluated to a Boolean value. Is this true?
In other words, as I understand it, the option without the == true line could be loosely described as follows:
Check X
While the option with the == true line would be more like:
Let Y be true if X is true, otherwise false
Check Y
Am I correct? Or perhaps any normal compiler/interpreter will do away with this difference? Or am I overlooking something, and there's really no difference at all?
Obviously, there will be no difference in terms of actual observed performance. Like I said, I'm just curious.
EDIT: Thanks to everyone who actually posted compiled results to illustrate whether the steps were different between the two approaches. (It seems, most of the time, they were, albeit only slightly.)
I just want to reiterate that I was not asking about what is the "right" approach. I understand that many people favor one over the other. I also understand that, logically, the two are identical. I was just curious if the actual operations being performed by the CPU are exactly the same for both methods; as it turns out, much of the time (obviously it depends on language, compiler, etc.), they are not.
I think the comparison with true shows a lack of understanding by your partner. Bools should be named things to avoid this (such as isAvailable: if (isAvailable) {...}).
I would expect the difference to be optimised away by any half-decent compiler.
(I just checked with C# and the compiled code is exactly the same for both syntaxes.)
The compiler should generate the same code. However, comparing with true is arguably better because it is more explicit. Generally I don't do the explicit comparison, but you shouldn't make fun of him for doing it.
Edit: The easiest way to tell is to try. The MS compiler (cl.exe) generates the same number of steps in assembly:
int _tmain(int argc, _TCHAR* argv[])
{
bool test_me = true;
if (test_me) {
004113C2 movzx eax,byte ptr [test_me]
004113C6 test eax,eax
004113C8 je wmain+41h (4113E1h)
printf("test_me was true!");
}
if (test_me == true) {
004113E1 movzx eax,byte ptr [test_me]
004113E5 cmp eax,1
004113E8 jne wmain+61h (411401h)
printf("still true!");
}
return 0;
}
At this point the question is do test and cmp have the same cost? My guess is yes, though experts may be able to point out differences.
The practical upshot is you shouldn't worry about this. Chances are you have way bigger performance fish to fry.
Duplicate question (Should I use `!IsGood` or `IsGood == false`?). Here's a pointer to my previous answer:
The technique of testing specifically
against true or false is bad practice
if the variable in question is really
supposed to be used as a boolean value
(even if its type is not boolean) -
especially in C/C++. Testing against
true can (and probably will) lead to
subtle bugs.
See the following SO answer for details:
Should I use `!IsGood` or `IsGood == false`?
Here is a thread which details the reasoning behind why "== true" is often false in more explicit detail, including Stroustrup's explanation:
https://qt-project.org/forums/viewthread/32642
In my experience if (flag==true) is bad practice.
The first argument is academic:
If you have a bool flag, it is either true or false.
Now, the expression
(flag==true)
again, is true or false - it is no more expressive, only redundant - flag can't get "more true" or "more false" than it already is. It would be "clearer" only if it's not obvious flag is a boolean - but there's a standard way to fix that which works for all types: choose a better name.
Stretching this beyond reason, the following would be "even better":
((flag==true)==true)
The second argument is pragmatic and platform-specific
C and early C++ implementations had no real "bool" type, so there are different conventions for flags, the most common being anything nonzero is true. It is not uncommon for API's to return an integer-based BOOL type, but not enforce the return value to be 0 or 1.
Some environments use the following definitions:
#define FALSE 0
#define TRUE (!FALSE)
good luck with if ((1==1) == TRUE)
Further, some platforms use different values - e.g. the VARIANT_BOOL for VB interop is a short, and VARIANT_TRUE is -1.
When mixing libraries using these definitions, an explicit comparison to true can easily be an error disguised as good intentions. So, don't.
Here's the Python (2.6) disassembly:
>>> def check(x): return (bool(x) == True)
>>> import dis
>>> dis.dis(check)
1 0 LOAD_GLOBAL 0 (bool)
3 LOAD_FAST 0 (x)
6 CALL_FUNCTION 1
9 LOAD_GLOBAL 1 (True)
12 COMPARE_OP 2 (==)
15 RETURN_VALUE
>>> def check2(x): return bool(x)
>>> dis.dis(check2)
1 0 LOAD_GLOBAL 0 (bool)
3 LOAD_FAST 0 (x)
6 CALL_FUNCTION 1
9 RETURN_VALUE
I suppose the reason check isn't optimized is due to Python being a dynamic language. This in itself doesn't mean Python uses a poor compiler, but it could stand to do a little type inference here. Maybe it makes a difference when a .pyd file is created?
There may be some justification in the "boolCheck == true" syntax dependning on the name of the variable you're testing.
For example, if the variable name was "state", then you can either have:
if (state) {
...
}
or you can have
if (state == true) {
...
}
In this case, I think the latter form is clearer and more obvious.
Another example would be a variable like "enabled", in which case the first form is clearer.
Now having a boolean variable called "state" is bad practice, but you may have no control over that, in which case the "== true" syntax may improve code readability.
This gets into specific languages and what they consider "truthy" values. Here's two common ones: JavaScript and PHP.
The triple equals operator in both these languages assures that you really are checking for a boolean type of truth. For example, in PHP checking for if ($value) can be different from if ($value==true) or if ($value===true):
$f = true;
$z = 1;
$n = null;
$a = array(1,2);
print ($f) ?'true':'false'; // true
print ($f==true) ?'true':'false'; // true
print ($f===true) ?'true':'false'; // true
print "\n";
print ($z) ?'true':'false'; // true
print ($z==true) ?'true':'false'; // true
print ($z===true) ?'true':'false'; // false
print "\n";
print ($n) ?'true':'false'; // false
print ($n==true) ?'true':'false'; // false
print ($n===true) ?'true':'false'; // false
print "\n";
print ($a) ?'true':'false'; // true
print ($a==true) ?'true':'false'; // true
print ($a===true) ?'true':'false'; // false
print "\n";
print "\n";
I expect that languages one speaks daily will inform how one views this question.
The MSVC++ 6.0 compiler generates slightly different code for the two forms:
4: if ( ok ) {
00401033 mov eax,dword ptr [ebp-8]
00401036 and eax,0FFh
0040103B test eax,eax
0040103D je main+36h (00401046)
....
7: if ( ok == true ) {
00401046 mov ecx,dword ptr [ebp-8]
00401049 and ecx,0FFh
0040104F cmp ecx,1
00401052 jne main+4Bh (0040105b)
The former version should be very slightly faster, if I remember my 8086 timings correctly :-)
It depends on the compiler. There might be optimizations for either case.
Testing for equality to true can lead to a bug, at least in C: in C, 'if' can be used on integer types (not just on boolean types), and accept any non-zero value; however the symbol 'TRUE' is one specific non-zero value (e.g. 1). This can become important with bit-flags:
if (flags & DCDBIT)
{
//do something when the DCDBIT bit is set in the flags variable
}
So given a function like this ...
int isDcdSet()
{
return (flags & DCDBIT);
}
... the expression "if (isDcdSet())" is not the same as "if (isDcdSet() == TRUE)".
Anyway; I'd think that an optimizing compiler should optimize away any difference (because there is no logical difference), assuming it's a language with a true boolean (not just integer) type.
There is no logical difference, presuming there is no internal typecasting going on, e.g., testing fstream.
ifstream fin;
...
if( ! fin)
...
It may not be the same if you are working with a nullable bool.
Example:
Bool? myBool = true
if(myBool) // This will not compile
if(myBool == true) //this will compile
IMHO it's a bad idea to use the if (boolCheck == true) form, for a simple reason : if you accidentally type a single 'equals' sign instead of a double (i.e. if (boolCheck = true)), it will assign true to boolCheck and will always return true, which would obviously be a bug. Of course, most modern compilers will show a warning when they see that (at least the C# compiler does), but many developers just ignore warnings...
If you want to be explicit, you should prefer this form: if (true == boolCheck). This will avoid accidental assignation of the variable, and will cause a compile error if you forget an 'equals' sign.