NSUInteger casting - objective-c

I have the following statement:
NSLog(#"The count of the book is now: %i", [book.book count]);
This gives me a caution that I'm using the wrong format argument.
1) Why can't I print the count as an integer? (Wouldn't this make the most sense?)
2) What would be the correct way to write the above statement?

You can, but probably shouldn't print it as a signed integer, because it may contain values that would overflow the signed integer. Additionally, NSUInteger is either defined as unsigned int, or unsigned long depending on wether the platform is 32 or 64 bit, so you can handle this by casting to unsigned long and then using the unsigned long format specifier.
NSLog(#"The count of the book is now: %lu", (unsigned long)[book.book count]);

Related

Objective C: Unsigned int compare

So I ran into a huge issue at work because I had something like this in my code:
int foo = -1;
NSArray *bar = [[NSArray alloc] initWithObjects:#"1",#"2",#"3", nil];
if (foo > [bar count]){
NSLog(#"Wow, that's messed up.");
} else {
NSLog(#"Rock on!");
}
As you probably already know by me posting this, the output is:
"Wow, that's messed up."
From what I gather, objective C is converting my negative number to a "signed" int and thus, killing my compare.
I saw other posts about this and they all stated what the problem was but none of them suggested any simple solutions to get this comparison to actually work. Also, I'm shocked that there are no compiler warnings, as these are causing serious issues for me.
The problem
The problem you're experiencing is that because foo is a signed integer and -[NSArray count] returns an unsigned integer, foo is undergoing implicit type conversion to unsigned integer. See Implicit Type Conversion for more information. Also, there's more information about type conversion rules in C here.
The solution
-[NSArray count] returns an unsigned value because an array can never have a negative number of elements; the smallest possible value is 0. Comparing an array's count to -1 doesn't make a lot of sense -- the count will always be larger than any negative number (sign problems notwithstanding).
So, the right solution here, and the way to avoid these kinds of problems, is to use a type that matches the return value of -[NSArray count], namely NSUInteger (the U is for unsigned).
Try this
- (IBAction)btnDoSomething:(id)sender {
int foo = -1;
NSArray *bar = [[NSArray alloc] initWithObjects:#"1",#"2",#"3", nil];
if ( foo > (signed)[bar count] ) {
NSLog(#"Wow, that's messed up.");
} else {
NSLog(#"Rock on!");
}
}
Working
If you are comparing two different type of variables then it will implicitly convert data type of both variables to higher type of them.
In this example,
variable foo is of type signed int and array count is of unsigned int,
So it will convert data type of foo to unsigned int
then value of foo will become large number, which is smaller than array count 3.
So in this example you need to down cast array count to signed int.
Issues
When your array count exceeds max limit of signed int then after casting it will rounded back like [ -(negative) max limit -> 0 -> + max limit ] which is unexpected result.
Solution
Avoid type casting if you are not sure about maximum array length.
Do casting if you are sure for limit(maximum array length will not exceeds signed int max limit).
For more details check this
http://visualcplus.blogspot.in/2006/02/lesson-4-casting-data-types.html

-1 < 4 return NO? It's so strange

int counter=-1;
NSArray *pointArray=[[NSArray alloc]initWithObjects:#"1",#"2",#"3",#"1",#"2", nil];
NSString *result=[NSString stringWithFormat:#"%d",counter<pointArray.count-1];
Believe it or not the result is 0 !!!
Try and who can tell me why???
You're comparing a signed number (-1) to an unsigned number (pointArray.count - 1).
Notice that the following code reproduces this issue:
#include <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
NSUInteger uns = 4;
int sig = -1;
BOOL cmp = (sig < uns);
NSLog(#"(%d<%zu)=%d", sig, uns, cmp);
}
The output of this is
(-1<4)=0
As has been pointed out, the trouble is that you are comparing an int to an NSUInteger. But recall that, on 64-bit systems, NSUInteger is a typedef of unsigned long.
The behavior we're seeing is a result of usual arithmetic conversion:
If either operand is of type long double, the other operand is converted to type long double.
If the above condition is not met and either operand is of type double, the other operand is converted to type double.
If the above two conditions are not met and either operand is of type float, the other operand is converted to type float.
If the above three conditions are not met (none of the operands are of floating types), then integral conversions are performed on the operands as follows:
If either operand is of type unsigned long, the other operand is converted to type unsigned long.
If the above condition is not met and either operand is of type long and the other of type unsigned int, both operands are converted to type unsigned long.
If the above two conditions are not met, and either operand is of type long, the other operand is converted to type long.
If the above three conditions are not met, and either operand is of type unsigned int, the other operand is converted to type unsigned int.
If none of the above conditions are met, both operands are converted to type int.
Since neither of the operands are of floating point type, we arrive at 4.. Since the second operand (pointArray.count-1) is of type NSUInteger, that is of type unsigned long, the other operand (counter) is converted to type unsigned long, taking on the value of 18446744073709551615 which is indeed greater than 4.

If statetement : I found something strange. Why is my second 'if' is equal to no?

If statetement : I found something strange. Why does my second 'if' is equal to no?
int a = bookSettings.tracks.count;
int b = _currentChapter - 1;
NSLog(#"a: %d", a);
NSLog(#"b: %d", b);
if (a > b)
NSLog(#"yes 1");
else NSLog(#"no 1");
if (bookSettings.tracks.count > (_currentChapter -1))
NSLog(#"yes 2");
else NSLog(#"no 2");
and log
a: 27
b: -1
yes 1
no 2
NSArray's -count method returns an NSUInteger -- an unsigned integer.
Using bookSettings.tracks.count in your if statement is likely causing both sides of the expression to be cast as NSUInteger. Even though _currentChapter - 1 equals -1, as an unsigned integer it is a very large number. So your track count is obviously less than that very large integer, which is why the if statement is yielding "no 2".
I believe that _currentChapter is a NSUInteger. When you assign it to b it becomes a signed integer and is therefore able to use -1. However, bookSettings.tracks.count is a unsigned integer and since _currentChapter is an unsigned integer as well, when you subtract 1 from _currentChapter (0, in this case) it actually becomes a very high integer.
you have not mentioned the type of bookSettings.tracks.count and if there is a mismatch between datatypes or object-types , the question comes down to true or false and the if statement will execute accordingly.
There might also be difference between NSInteger ans trivial c int.

How to do string related problem

I am making a binary to decimal number converter on iphone. having some problem when i trying to take each single digit from a number and do calculation. I tried char, characterAtIndex but they all failed to do calculation or i got the syntax completely wrong. Can anyone show me how to do such cast or there is an easier approach?
Your problem is getting numbers from strings?
The easiest way to get an integer from a character is to use the ascii table, like this:
NSString *stringOfNums = #"15";
char c;
int num;
for (int i = 0; i < [stringOfNums length]; ++i) {
c = [stringOfNums characterAtIndex:i];
num = c - 48; // 0 is 48 in ascii table
printf("\nchar is %c and num is %d", c, num);
}
The advantage of this method is that you can validate on a char-by-char basis that each falls in a range of 48 through 57, the ascii digits.
Or you could do the conversion in one step using NSNumberFormatter, as described here: How to convert an NSString into an NSNumber
As for the binary-decimal conversion, does your formula work on paper? Get that right first.

Division and NSUInteger

I have some calculation that involves negative values:
row = (stagePosition - col) / PHNumRow;
Say stagePosition is -7 and col is 1. They are both NSInteger, including row.
PHNumRow is 8.
If PHNumRow is NSInteger, I get the result I expect: -1.
But if PHNumRow is NSUInteger, the result is garbage.
Why should it matter if the divisor is unsigned or signed?
I'm not putting the result in an unsigned int.
Because of integer promotion. When the right hand side is evaluated, all arguments are promoted to the highest type of the operands of the expression which, if PHNumRow is unsigned, will be unsigned integer. The compiler does something similar to the following:
((NSUInteger)stagePosition - (NSUInteger)col) / PHNumRow;
Since, stagePosition is negative, there is a wraparound and your computation goes boom!