If you have an object like NSString *someString, what is the difference, if any, between
if (!someString)
vs
if (someString == nil)
Thanks!
If you have an object like NSString *someString, what is the difference, if any, between
if (!someString)
vs
if (someString == nil)
Thanks!
The first syntax you use:
if (!someString)
exploits a sort of "ambiguity" of C deriving from the fact that the original standard of C lacked a proper boolean type. Therefore, any integer value equalling 0 was interpreted as "false", and any integer value different from "0" was taken as "true". The meaning of !
is therefore defined based on this convention and current versions of the C standard have kept the original definition for compatibility.
In your specific case, someString
is a pointer, so it is first converted to an integer, then ! someString
is interpreted as a bool value of true
when someString
points at the location 0x000000
, otherwise it evals to "true".
This is fine in most conditions (I would say always), but in theory, NULL/nil
could be different from 0x000000
under certain compilers, so (in very theory) it would be better to use the second syntax, which is more explicit:
if (someString == nil)
It is anyway more readable and since someString
is not an integer (rather a pointer), IMO, better practice in general.
EDIT: about the definition of NULL...
Whether the C standard defines NULL to be 0 is an interesting topic for me...
According to C99 standard, section 7.17, "Common definitions ":
NULL [which] expands to an implementation-defined null pointer constant;
So, NULL is defined in stddef.h to an implementation-defined null pointer constant... The same document on page 47 states:
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
So, the null pointer constant (which is (void*)0
) can be converted to a null pointer and this is guaranteed to compare unequal to a pointer to any object or function.
So, I think that basically it depends on whether the implementation decides that the result of converting a null pointer constant to a null pointer produces a pointer which converted back to an integer gives 0. It is not clear that a null pointer interpreted as an integer equals 0.
I would say that the standard really try and enforce the null pointer being 0, but leaves the door open to systems where the null pointer was not 0.
For most pointers, they're equivalent, though most coders I know prefer the former as it's more concise.
For weakly linked symbols, the former resolves the symbol (and will cause a crash if it's missing) while an explicit comparison against nil
or NULL
will not.
The bang, exclamation, !
prefix operator in C is a logical not. At least, its a version of it. If you looked at a typical logical not truth table you would see something like this:
Input Result
1 0
0 1
However in C the logical not operator does something more like this:
Input Result
non-zero 0
0 1
So when you consider that both NULL and nil in Objective-C evaluate to 0, you know that the logical not operator applied to them will result in a 1.
Now, consider the equality ==
operator. It compares the value of two items and returns 1 if they are equal, 0 if they are not. If you mapped its results to a truth table then it would look exactly like the results for logical not.
In C and Objective-C programs, conditionality is actually determined by int's, as opposed to real booleans. This is because there is no such thing as a boolean data type in C. So writing something like this works perfectly fine in C:
if(5) printf("hello\n"); // prints hello
and in addition
if(2029) printf("hello\n"); // also prints hello
Basically, any non-zero int will evaluate as 'true' in C. You combine that with the truth tables for logical negation and equality, and you quickly realize that:
(! someString) and (someString == nil)
are for all intents identical!
So the next logical question is, why prefer one form over another? From a pure C view-point it would be mostly a point of style, but most (good) developers would choose the equality test for a number of reasons:
In your case it means the same thing. Any pointer that does not point to nil
will return YES
(true).
Normally the exclamation mark operator negates a BOOL
value.
If you mean to test the condition "foo is nil" you should say that: foo == nil
.
If you mean to test a boolean value for falsehood, !foo
is okay, but personally I think that a skinny little exclamation point is easy to miss, so I prefer foo == NO
.
Writing good code is about clearly conveying your intention not just to the compiler, but to the next programmer that comes along (possibly a future you). In both cases, the more explicit you can be about what you're trying to do, the better.
All that aside, !
and ==nil
have the same effect in all the cases I can think of.
!
is a negation operator. If your object isn't allocated, you will reach the same result from a truth table as you would with an == nil
operation.
But, ! is usually more used for boolean operations.
if(!isFalse) {
//if isFalse == NO, then this operation evaluates to YES (true)
[self doStuff];
}
When you use !
on an object like !something
it just checks to see if the pointer is pointing to nil
, if it doesn't, it returns true, and the if statement fires.