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

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.

Related

Structure of a block declaration

When declaring a block what's the rationale behind using this syntax (i.e. surrounding brackets and caret on the left)?
(^myBlock)
For example:
int (^myBlock)(int) = ^(int num) {
return num * multiplier;
};
C BLOCKS: Syntax and Usage
Variables pointing to blocks take on the exact same syntax as variables pointing to functions, except * is substituted for ^. For example, this is a function pointer to a function taking an int and returning a float:
float (*myfuncptr)(int);
and this is a block pointer to a block taking an int and returning a float:
float (^myblockptr)(int);
As with function pointers, you'll likely want to typedef those types, as it can get relatively hairy otherwise. For example, a pointer to a block returning a block taking a block would be something like void (^(^myblockptr)(void (^)()))();, which is nigh impossible to read. A simple typedef later, and it's much simpler:
typedef void (^Block)();
Block (^myblockptr)(Block);
Declaring blocks themselves is where we get into the unknown, as it doesn't really look like C, although they resemble function declarations. Let's start with the basics:
myvar1 = ^ returntype (type arg1, type arg2, and so on) {
block contents;
like in a function;
return returnvalue;
};
This defines a block literal (from after = to and including }), explicitly mentions its return type, an argument list, the block body, a return statement, and assigns this literal to the variable myvar1.
A literal is a value that can be built at compile-time. An integer literal (The 3 in int a = 3;) and a string literal (The "foobar" in const char *b = "foobar";) are other examples of literals. The fact that a block declaration is a literal is important later when we get into memory management.
Finding a return statement in a block like this is vexing to some. Does it return from the enclosing function, you may ask? No, it returns a value that can be used by the caller of the block. See 'Calling blocks'. Note: If the block has multiple return statements, they must return the same type.
Finally, some parts of a block declaration are optional. These are:
The argument list. If the block takes no arguments, the argument list can be skipped entirely.
Examples:
myblock1 = ^ int (void) { return 3; }; // may be written as:
myblock2 = ^ int { return 3; }
The return type. If the block has no return statement, void is assumed. If the block has a return statement, the return type is inferred from it. This means you can almost always just skip the return type from the declaration, except in cases where it might be ambiguous.
Examples:
myblock3 = ^ void { printf("Hello.\n"); }; // may be written as:
myblock4 = ^ { printf("Hello.\n"); };
// Both succeed ONLY if myblock5 and myblock6 are of type int(^)(void)
myblock5 = ^ int { return 3; }; // can be written as:
myblock6 = ^ { return 3; };
source: http://thirdcog.eu/pwcblocks/
I think the rationale is that it looks like a function pointer:
void (*foo)(int);
Which should be familiar to any C programmer.

If (BOOL) in Objective C: unused variable

In an implementation of a CGRect, I attempt this:
BOOL didStartPressing = NO;
if ( didStartPressing) {int nmax=5;}
else{int nmax=500;}
for (int n=1; n<nmax; n=n+1){ *... working code that draws some circles ....* }
This gives yellow warnings about "unused variable nmax" in the first part above
and red warnings about "use of undeclared variable nmax." for the for loop.
If however I simply replace the first three lines above with
int nmax=500;
I get a lovely picture that I drew in CGRect.
Greatest of thanks for help, as I'm complete noob up against the hard wall of learning curve.
You've limited the scope of nmax to the braces after the if and the else. So you have two variables with that name, neither of which is visible to the for loop. To solve, move the declaration to the outer scope and simply assign to the variable in the if/else scopes:
int nmax = 0; // the = 0 is optional in this case because all code
// paths assign a value to nmax
BOOL didStartPressing = NO;
if (didStartPressing) {
nmax=5;
} else {
nmax=500;
}
for (int n=1; n<nmax; n=n+1) {
/*... working code that draws some circles ....*/
}
This is a C language thing. The scope of a variable that's declared inside a pair of braces is only the section inside the braces. That means you have two different variables, both called nmax and each limited to its section of the if/else statement.
You can make it work with:
int nmax = 500;
if ( didStartPressing) {
nmax=5;
}
Look at a book on C programming for more details.

Can an If Statement tell if an assignment was valid?

I have an object that returns a value if successful and false (or nil) if it failed.
i want to assign that value to a variable
if(var1 = [object foo])
{
//if the [object foo] returned a variable, goes here
}
else
{
//[object foo] returned FALSE (or nil), go here
}
can an If statement detected if an assignment was valid?
This is all right but will generate a warning, since this is a common typo (= instead of ==). To silence that warning add another set of parentheses like this:
if ((var = [object foo])) ...
Since this easily can lead to misunderstandings a lot of people will advise against doing this. For a simple if statement this is much clearer to do the assignment first:
var = [object for];
if (var) ...
In while loops this is more useful, but also considered harmful by many people.
Not sure I understand your question, but let me try and explain a few situations you can check
1) Property contains value
if ([object foo])
{
// If foo has a value associated to it that is not nil/false/zero
}
else
{
// If foo equals nil, false or zero
}
2) Assignment to a variable was successful
if ((bar = [object myMethod]))
{
// If myMethod returns any non-nil value
}
else
{
// If myMethod returns nil
}
3) Previous assignment of a variable was successful
bar = [object myMethod];
if (bar)
{
// If bar has a value associated to it that is not nil/false/zero
}
else
{
// If bar equals nil, false or zero
}
use == instead of = in the if statement.
before the if statement, you may have var1 = [object foo]
see comparison operators
If you mean by valid that the variable contains an expected result, you can just perform another if on the variable against the expected result, or null to check it.

"used struct type value where scalar is required" at .layer.position

I want to make a selection before apply one of two animations,
what I thought is: make a Point one, if my myImageView is at the Point one, then apply animationNo1, else apply animationNo2, but I got this:"used struct type value where scalar is required", at line if (myImageView.layer.position = one)
What I do? how can I fix this?
Does anyone know exactly what makes the problem happen?
CGPoint one = CGPointMake(myImageView.layer.position.x, 100);
if (myImageView.layer.position = one)
{
animationNo1
}
else
{
animationNo2
}
First of all, your if-statement will not do what you think. If you want to compare something you have to use == (ie 2 =)
and you can't compare CGPoints like this.
use
if (CGPointEqualToPoint(one, self.view.layer.position))
if (myImageView.layer.position = one) { animationNo1 }
should be
if (CGPointIsEqualToPoint(myImageView.layer.position, one)) { animationNo1 }
You used a single = meaning assignment, rather than a == for comparison. But the == wouldn't do what you wanted here anyway.
You are passing a struct (int this case position) instead of a scalar. To do what you want you need to use CGPointIsEqualToPoint:
if (CGPointEqualToPoint(one, self.view.layer.position))
Full code with corrections:
CGPoint one = CGPointMake(myImageView.layer.position.x, 100);
if (CGPointEqualToPoint(one, self.view.layer.position))
{
animationNo1
}
else
{
animationNo2
}
Also, as others have pointed out: Be careful about = vs ==. They are different. In this case you don't use == for comparison fortunately, but if you use = for other stuff it will make it true instead of checking to see if it is 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.