NSInteger и NSUInteger в смешанной среде с 64 бит /32 бит

У меня есть множество спецификаторов формата строки в вызовах NSLog/NSAssert и т.д., которые используют %d и %u с типами NSInteger (= int on 32bit) и NSUInteger (= unsigned int on 32bit) соответственно.

При преобразовании приложения в 64 бит это дает предупреждения (конечно), поскольку ожидается %ld %lu для того, что теперь стало типом long и unsigned long.

Простое преобразование спецификаторов формата, конечно, представит обратные предупреждения в 32-битной сборке.
Таким образом, единственное решение, которое я вижу, чтобы стать предупреждающим, - это использование 64-битных спецификаторов и приведение к 64-битным значениям везде, где в 32-битной сборке содержится предупреждение.

Но мне было интересно, могут ли быть спецификаторы формата специально для типов NSInteger и NSUInteger, которые будут работать на обеих архитектурах без кастования?

Ответ 1

Я думаю, что самый безопасный способ - поместить их в экземпляры NSNumber.

NSLog(@"Number is %@", @(number)); // use the highest level of abstraction

Этот бокс обычно не должен создавать новый объект благодаря методу указателя.

Если вы действительно не хотите использовать NSNumber, вы можете использовать примитивные типы вручную, как предложили другие:

NSLog(@"Number is %ld", (long)number); // works the same on 32-bit and 64-bit

Ответ 2

Вы также можете использовать %zd (NSInteger) и %tu (NSUInteger) при входе в консоль.

NSInteger integer = 1;
NSLog(@"first number: %zd", integer);

NSUInteger uinteger = 1;
NSLog(@"second number: %tu", uinteger);

Также можно найти здесь.

Ответ 3

Нет (к сожалению) нет формата printf, который непосредственно соответствует NS(U)Integer. Итак, для независимого от архитектуры кода вам нужно преобразовать все в "длинный" вариант (как предполагает Xcode "Fix-it" ):

NSInteger i = ...;
NSLog(@"%ld", (long)i);

Единственная альтернатива, которую я знаю, это Типы Foundation при компиляции для arm64 и 32-битной архитектуры:

// In the precompiled header file:
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

NSInteger i = ...;
NSLog(@"i=%"NSI, i);

с использованием макросов препроцессора (но даже автор этого ответа называет это "по общему признанию, ужасный подход" ).