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

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.

Related

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.

Comparing two BOOL values

In my instance method, would like to compare a BOOL parameter with the content of a static variable, for instance:
- (NSArray*)myMethod:(NSString*)someString actualValuesOnly:(BOOL)actualValuesOnly {
static NSString *prevSsomeString;
static BOOL prevActualValuesOnly;
static NSArray *prevResults
if ([someString isEqualToString:prevSomeString] &&
([actualValuesOnly isEqual: prevActualValuesOnly])
// HOW TO COMPARE THESE TWO BOOLEANS CORRECTLY??
{ return prevResults; }// parameters have not changed, return previous results
else { } // do calculations and store parameters and results for future comparisons)
What would be the correct way to do this?
Since BOOL is a primitive (or scalar) type, and not a class, you can compare it directly with ==
if ([someString isEqualToString:prevSomeString] && actualValuesOnly == prevActualValuesOnly)
Boolean variable is compare with == sign instead of isEqual
if(Bool1 == Bool2){
// do something here}
Boolean is compare with == sign instead of isequal:
The solutions mentioned here are not the safest way to compare 2 BOOL values, because a BOOL is really just an integer, so they can contain more than just YES/NO values. The best way is to XOR them together, like detailed here: https://stackoverflow.com/a/11135879/1026573
As Matthias Bauch suggests,
Simply do the comparison using == operator i.e
if (BOOL1 == BOOL2)
{
//enter code here
}

Is there alternative of the "<=>" operator from Perl in C/Objective-C?

I'm implementing some custom NSArray sort selectors and I was wondering whether there's anything like the <=> operator in C/Objective-C?
I have this:
if (self.count == otherObject.count) return 0;
return (self.count > otherObject.count)? 1 : -1;
and would love to have (as in Perl)
return self.count <=> otherObject.count;
Maybe the compare: method is what you are looking for? NSString, NSNumber etc implement it. All compare-like methods in Cocoa returns a NSComparisonResult:
enum {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
};
typedef NSInteger NSComparisonResult;
So you can use the returned integer value directly. Assuming that count in your question is a NSNumber you can do:
return [self.count compare:otherObject.count];
If your case is limited to numbers and you want to use just an operator you can probably use good old minus. But be aware of integer overflow!:
return self.count - otherObject.count;
It's called the Spaceship Operator and it originated in Perl; besides Perl, only Ruby and Groovy have it.
Not in C, and probably not in Objective-C.
You could write a function easily enough, though it would be specific to a particular operand type:
int compare(int x, int y) {
return x < y ? -1 : (x > y);
}
Or you could write a macro, which could be applied to any type with <, ==, and > operators, but it would sometimes evaluate its arguments more than once:
#define COMPARE(x, y) ((x) < (y) ? -1 : ((x) > (y)))
(Note that both versions depend on the > operator yielding 0 for false, 1 for true.)

Is comparing a BOOL against YES dangerous?

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.

Arithmetic with pointer types/

Some examples of adding and subtracting similarly typed pointers, using numeric and character pointers please. Using C.
Thanks.
You can check this to know about pointer arithmetic
Here's a practical example which extracts a single character from a C string:
char charAt( char *str, size_t idx) {
if (idx > strlen (str))
return '\0';
return *(str+idx);
}
Or another, which swaps an integer in an array with the one immediately before it (with no range checking):
void swapInts( int *base, size_t idx) {
tmp = *(base+idx);
*(base+idx) = *(base+idx-1);
*(base+idx-1) = tmp;
}
In both these cases, *(pointer+offset) is identical to pointer[offfset] but using pointer arithmetic instead of array offsets:
*(str+idx) -> str[idx]
*(base+idx) -> base[idx]
*(base+idx-1] -> base[idx-1]
Warning: Don't use these verbatim in your homework, have a think about them then write your own. If you copy them verbatim, you will almost certainly be failed since your educators no doubt watch these sites as well.