Upgrading XCode caused warning for hex Format Specifier - objective-c

The following line of code:
[colHeader appendFormat:#"%C", 0x2193];
throws this warning:
Format specifies type 'unsigned short' but the argument has type 'int'
This started appearing when I upgraded to Xcode 4.4 (upgraded compiler?). The warning will drive me nuts...any suggestions on how to remove it? Thanks.

Well, the easiest thing is just to cast it, I guess:
[colHeader appendFormat:#"%C", (ushort) 0x2193];
You can specify that a value is unsigned by appending a "u", e.g., 0x2193u. However, the constant will then be an unsigned int, not an unsigned short, so that won't help you here as you would still get a warning.

Related

Xcode warning: Format specifies type 'long' but the argument has type 'int _Nullable'

I get this warning for the following line of code:
NSLog(#"selected segment: %li", _segmentControl.selectedSegmentIndex);
The property selectedSegmentIndex is of type NSInteger.
If I change the format to %i i get the following warning:
Format specifies type 'int' but the argument has type 'long _Nullable'
Are there any new format specifiers for Nullable types or is this just a bug in Xcode 7?
You should type:
NSLog(#"selected segment: %li", (long)_segmentControl.selectedSegmentIndex);
Because NSInteger has a different length in 32 and 64bit architecture. Previously you didn't see the warning, because probably you was compiling only against 64 bit architecture.
I'd also advise to read Apple Article, as there are new specifiers in Xcode 7 (among others nullable and nonnull).
To answer your doubts from the comment, please refer to this Apple document, where they state the following:
Type Specifiers
Script action: Warns about potential problems; may generate false negatives.
Typically, in 32-bit code you use the %d specifier to format int
values in functions such as printf, NSAssert, and NSLog, and in
methods such as stringWithFormat:. But with NSInteger, which on 64-bit
architectures is the same size as long, you need to use the %ld
specifier. Unless you are building 32-bit like 64-bit, these
specifiers generates compiler warnings in 32-bit mode. To avoid this
problem, you can cast the values to long or unsigned long, as
appropriate. For example:
NSInteger i = 34;
printf("%ld\n", (long)i);
Just want to add :
I got this warning "suddenly" even when I did not change the code that made the warning for long time, and I did not understand why it's appear.
The reason : "Generic iOS Device".
when selected device or simulator, the warnings disappear.
still, I add to the NSLog "(long)" to the variables. till then I only had "%ld", that turn the warning no matter what was selected (generic device, real device, simulator)

How to remove 100s of warnings "implicit conversion loses integer precision: 'NSInteger' (aka 'long') to 'int'" I got after updating to arm64?

Problem:
Yesterday I converted a large project of mine to support arm64 and after that I got 500+ warnings at once. About 70% of them are where NSInteger is being assigned to int or vice versa, and remaining are where NSUInteger is formatted in NSString like this:
NSInteger a = 123;
NSString *str = [NSString stringWithFormat:#"Int:%d", a]; //warning: value of 'NSInteger' should not be used as formate argument; add an explicit cast to 'unsigned long' instead.
Now I do know how to adress them manually, but that's a huge task and very laborious.
I'm also aware that I can silence the type mismatch warnings all together, but I don't want to do that. Of course, they're very helpful.
What I've tried:
I've converted [NSNumber numberWithInt:abc]; to [NSNumber numberWithInt:(int)abc]; using find-n-replace. It fixed some.
I've also tried to change all my int properties to NSInteger properties
but it doubled the number of warnings (reached to 900+ count). So I
reverted.
I've also tried to find some regular expression but couldn't find
something suitable to my needs.
Question:
I'm looking for a regular expression or any other workaround somebody has tried which can reduce the amount of work needed to fix them manually.
Thanks in advance.
NSInteger a = 123;
NSString *str = [NSString stringWithFormat:#"Int:%ld", (long)a];
After updating to 64 bit need to do typecast like this((long)a). %d is only for 32 bit range %ld for long integer. For better understanding got through this apple documentation.
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Cocoa64BitGuide/ConvertingExistingApp/ConvertingExistingApp.html
In case someone else's facing a similar situation, I want to clarify how to deal with it. Although #Raju's answer is suggesting to do it manually (which I wanted to avoid), I found exactly what I needed at the link he shared.
Apple has provided a script for 64bit conversion called ConvertCocoa64, located at/Developer/Extras/64BitConversion/ConvertCocoa64 which not only converts all int to NSInteger it also deals with float to CGFloat conversion, as stated:
It converts most instances of int and unsigned int to NSInteger and
NSUInteger, respectively. It doesn't convert ints in bit-field
declarations and other inappropriate cases. During processing, the
script refers to a hardcoded list of exceptions.
In addition to above conversions it also flags the lines in code which need manual fix. So this might help with the warnings of String Formats.
Please refer to this link for complete details. It not only explains how to use the script but also suggests some very important post 64-bit migration check points.
objective c implicit conversion loses integer precision 'NSUInteger' (aka 'unsigned long') to 'int
Change key in Project > Build Setting "implicit conversion to 32Bits Type > Debug > *64 architecture : No"
Other warning
Change key in Project > Build Setting "typecheck calls to printf/scanf : NO"
Explanation : [How it works]
Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense.
Hope it work
[caution: It may void other warning of 64 Bits architecture conversion].

format descriptor for unsigned short * in IOS 6

In my code I have some strings in unichar format with definition like below
unichar sourceString[100];
After I assign value to sourceString, I need to put it into an NSString with proper format descriptor.
Previously in IOS 5, I used %S, and it worked just fine. The code is as follows
NSString * targetString = [NSString stringWithFormat:#"%S",sourceString];
But after I upgraded SDK to IOS 6.0, warnings comes up with the same code:
**Format specifies type 'const unsigned short *' but the argument has type 'unichar *' (aka 'unsigned short *')**
My app still works but there are hundreds of warnings when the code is compiled, which is really annoying.
I am wondering what is the correct format descriptor I shall use in this case?
Thanks!
Using const unichar sourceString[100]; will solve your problem.
If you try using %hu the warning still appears?
Seeing format types at: http://reference.jumpingmonkey.org/programming_languages/objective-c/types.html

Unicode formatting compiler warning: Format specifies type 'unsigned short' but the argument has type 'int'

It's a tad OCD, but I hate getting any compiler warnings. When I updated XCode, I started getting this compiler warning:
Format specifies type 'unsigned short' but the argument has type 'int'
When I tried including the Unicode character for degree using the following code:
currentVal = [NSString stringWithFormat:#"%.2f%C", angleDeg, 0x00B0];
How do I make the compiler warning go away, either by changing the code or turning off that particular compiler warning?
Cast the literal to unichar:
currentVal = [NSString stringWithFormat:#"%.2f%C", angleDeg, (unichar)0x00B0];

Why does only NSLog warn me about using the %lu string format specifier for NSUInteger?

For some reason, I get a compilation error when I try to do the following:
NSLog(#"row: %lu", indexPath.row);
where row is of type NSUInteger. The error I get is
Conversion specifies type 'unsigned long' but the argument has type 'NSUInteger' (aka 'unsigned int')
I can do the following with no compilation errors:
NSString * string = [NSString stringWithFormat:#"row: %lu", indexPath.row];
I'm using the exact same format string and substitution argument in both cases, but why does NSLog freak out while -stringWithFormat: seems to be perfectly content? My compiler is LLVM 1.6.
All devices that iOS currently runs on are 32-bit. If you want to silence the warning:
NSLog(#"row: %lu", (unsigned long)indexPath.row);
[Edit: As of the iPhone 5s, it is no longer true that iOS is always 32-bit.]
I've run into this same issue, and although #Wevah is correct and his answer works just fine, there's another option that doesn't require any code changes. See the following Apple documentation for details:
String Programming Guide | Platform Dependencies
64-Bit Transition Guide for Cocoa | Building 32-Bit Like 64-Bit
The NS_BUILD_32_LIKE_64 preprocessor macro is quite helpful. You can set it in your Xcode project settings (under GCC_PREPROCESSOR_DEFINITIONS) or just put #define NS_BUILD_32_LIKE_64 1 in your precompiled header (.pch) file. In my app, this eliminated 11 warnings without any code changes.
This works because unsigned int and unsigned long are the same size (4 bytes) on iOS, so changing the typedef of NSUInteger makes the compiler (and the developer) happy, but the hardware doesn't care, since it's just doing integer math in both cases. :-)
Apple documentation recommends casting the 64 bit value to a 32 bit value using %lu and %ld. This poses a problem if you actually use the extra 32 bits. Format strings %qu and %qd specify a 64 bit value (unsigned and signed respectively). If you want code that will compile in either mode, then values declared as NSUInteger or NSInteger will have to be cast to a UInt64 or SInt64 in the parameter list to avoid the warning.