2013-03-04 2 views
0

Глядя в заголовки, я вижу, что для 64-битной системы, которую я компилирую, как NSUInteger, так и UInt32 определены как 32-разрядные целые числа без знака, поэтому почему Xcode утверждает потерю точности в предупреждении, когда я назначаю один к другому?Какао: NSUInteger и UInt32 оба определены как 32-разрядное целое без знака. Так почему же предупреждения?

«Неявное преобразование теряет целочисленную точность:„NSUInteger“(он же„неподписанных долгое“) для„UInt32“(он же„неподписанных Int“)»

я могу видеть, что предупреждение имеет в виду одно, как «длинный 'и один как' int ', но поскольку оба они разрешают одно и то же 32-битное целое число без знака в этой системе, не должно быть потери точности.

На самом деле это не вызывает никаких проблем, но, похоже, я, вероятно, неправильно понял что-то, поэтому хотел бы лучше понять.

Был этот вопрос, но он обращается к безопасности, в отличие от «почему»: Can I safely store UInt32 to NSUInteger?

+0

Возможно, потому что NSUInteger может быть 64 бит в длину на других системах. – Rakesh

ответ

2

NSUInteger и NSInteger можно использовать даже в прошивке, а также в OSX.

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64 
    typedef long NSInteger; 
    typedef unsigned long NSUInteger; 
#else 
    typedef int NSInteger; 
    typedef unsigned int NSUInteger; 
#endif 

IOS являются 32 бит устройства, тогда как OSX является 64 бит (ранее OSX было 32 бит и даже вы можете выбрать, чтобы сделать приложение для 32-битных ОС), поэтому она содержит if-else directive, на основании которого он установлен.

В OSX я всегда использую %ld с NSInteger, но в iOS он должен быть %d.

Если вы используете %d для NSInteger, оно отображает предупреждение. Прерывает целочисленную точность.

+0

Как насчет того, когда вы компилируете для 32-бит под OSX? – trojanfoe

+0

ОК, спасибо Anoop. Что касается того, как работает компилятор, означает ли это, что он вычисляет предупреждения * до того, как * он разрешил директиву if-else, так что пока не осознает, что это не нужно? –

+0

@trojanfoe: в этом случае это будет 32 бит, как из директивы if-else –

4

На 64-битной OS X платформы:

  • NSUInteger определяется как unsigned long и
  • unsigned long представляет собой 64-битовое целое число без знака.

Так UInt32 и NSUIntegerделать не имеют тот же размер, что и объясняет предупреждение компилятора.

Смотрите также NSUInteger в "Типы данных Foundation Reference":

При создании 32-разрядных приложений, NSUInteger является 32-разрядное беззнаковое целое число . 64-разрядное приложение рассматривает NSUInteger как 64-разрядное целое число без знака .

Примечание: 64-разрядный OS X использует (как многие Unix и Unix-подобные системы) модели данных LP64, что означает, что длинные и указателей имеют 64-разрядные. 64-битная Windows использует модель данных IL32P64, где длинный имеет 32-разрядные и указатели имеют 64-разрядную версию.

+0

Спасибо, я думаю, что я noob при интерпретации заголовков в MacTypes.h: UInt32 32-разрядное целое без знака ... typedef unsigned int UInt32; и в NSObjCRuntime.h: #if __LP64__ || (TARGET_OS_EMBEDDED &&! TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64 typedef long NSInteger; typedef unsigned long NSUInteger; –

+1

@JoeyFourSheds: Да, это именно то место, где оно определено. '__LP64__' является истинным на 64-битной платформе, NSUInteger определяется как unsigned long, а unsigned long имеет 64-разрядную версию на 64-битной платформе! - Поскольку Uint32 имеет только 32-битный, у вас есть возможная потеря точности. –

+0

Спасибо. (и извините за беспорядочный комментарий, похоже, не может сделать новую строку в комментарии, поэтому он получил примерно 6 раз каждый раз, когда я обычно нажимаю «return»!). –