Objective-C örtük dönüştürme 'NSUInteger' ('imzasız uzun') tamsayı hassasiyetini 'int' uyarısına kaybeder


187

Bazı alıştırmalar üzerinde çalışıyorum ve şunları belirten bir uyarı var:

Örtük dönüşüm tamsayı hassasiyetini kaybeder: 'NSUInteger' (aka 'unsigned long') 'int'

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
    @autoreleasepool {

        NSArray *myColors;

        int i;
        int count;

        myColors = @[@"Red", @"Green", @"Blue", @"Yellow"];

        count = myColors.count; //  <<< issue warning here

        for (i = 0; i < count; i++)

        NSLog (@"Element %i = %@", i, [myColors objectAtIndex: i]);
    }

    return 0;
}

Ekran görüntüsü

Yanıtlar:


470

countYöntem NSArraydöndürür bir NSUInteger, ve 64-bit OS X platformunda

  • NSUIntegerolarak tanımlanır unsigned longve
  • unsigned long 64 bit işaretsiz bir tam sayıdır.
  • int 32 bitlik bir tam sayıdır.

Bu nedenle derleyici uyarısından intdaha küçük bir "veri tipi" dir NSUInteger.

Ayrıca , "Temel Veri Türleri Başvurusu" nda NSUInteger'a bakın :

32 bit uygulamalar oluştururken, NSUInteger 32 bit işaretsiz bir tam sayıdır. 64-bit bir uygulama NSUInteger'ı 64-bit işaretsiz bir tam sayı olarak ele alır.

Derleyici uyarısını düzeltmek için, yerel countdeğişkeni şu şekilde bildirebilirsiniz:

NSUInteger count;

veya (dizinizin hiçbir zaman 2^31-1öğeden daha fazlasını içermeyeceğinden eminseniz ), açık bir kadro ekleyin:

int count = (int)[myColors count];

19
Sadece eklemek için - Xcode 5 projemde aniden bir sürü uyarı ve hata aldım, bu cevaba oy verdim. Yapım ayarlarıma bakmamı sağlayan 64bit'ten bahsettin. Xcode 64bit moduna değiştirdi ve hatalar attı. Bunu arvm7 olarak değiştirmek hepsini düzeltti.
Robert J. Clegg

1
@Tander derleme 64bit vs armv7 arasında bir performans farkı var mı?
Shaun Budhram

1
@ShaunBudhram Görünüşe göre hayır. Hiç bir fark görmedim. Sadece CPU'yu yoğun kullanan uygulamalarda bir fark yaratacaktır - örneğin oyunlar 64 bit için derleme avantajı görür.
Robert J. Clegg

7
"1 Şubat 2015'ten itibaren App Store'a yüklenen yeni iOS uygulamaları 64 bit destek içermelidir ..." - Apple Developer News ve Güncellemeler, 20 Ekim 2014
Pang

2
@JayprakashDubey: İkili derlenmiş uygulamayı App Store'a gönderdiğiniz için Apple derleyici uyarılarınızı görmez. Bu nedenle, uygulamanız derleyici uyarıları nedeniyle reddedilemez. Tabii ki uygulamanızın düzgün çalışması için bunları düzeltmelisiniz.
Martin R

24

Martin'in cevabının aksine, dizinizde 2 ^ 31-1'den fazla öğe bulunmadığını bilseniz bile int (veya uyarıyı yoksaymak) için yayın yapmak her zaman güvenli değildir. 64 bit için derleme yaparken olmaz.

Örneğin:

NSArray *array = @[@"a", @"b", @"c"];

int i = (int) [array indexOfObject:@"d"];
// indexOfObject returned NSNotFound, which is NSIntegerMax, which is LONG_MAX in 64 bit.
// We cast this to int and got -1.
// But -1 != NSNotFound. Trouble ahead!

if (i == NSNotFound) {
    // thought we'd get here, but we don't
    NSLog(@"it's not here");
}
else {
    // this is what actually happens
    NSLog(@"it's here: %d", i);

    // **** crash horribly ****
    NSLog(@"the object is %@", array[i]);
}

6
Sonucu yayınlamanın indexOfObject:kötü bir fikir olacağı konusunda haklısınız . Cevabım sorudaki özel kod içindi ve countyöntem geri dönemiyor NSNotFound. Uyarıları genel olarak almayı veya yoksaymayı önermedim. Bu net değilse özür dilerim. Aslında, örnek kodunuz if (i == NSNotFound)64 bit için derlendiğinde bir uyarı oluşturur , bu nedenle sorun fark edilmez.
Martin R

@Adrian: Sakıncası yoksa, askerin ne yapmasını önerirsiniz?
moonman239

@ moonman239 Genel olarak, dökümün (ikincisinin) aksine, mümkünse doğru tipte bir değişken (@ MartinR'nin ilk önerisi) kullanırdım. Belirttiği gibi, bu özel durumda döküm güvenlidir, ancak bence beklenmedik sonuçları olabileceğinden (örneğimde olduğu gibi) girmesi kötü bir alışkanlık. (Bu == derleyici uyarı hakkında iyi bir nokta olmasına rağmen, kaçırmış olmalıyım) bu özel durum tarafından ısırıldı çünkü yayınlanmıştır.
Adrian

2
Ben sayısı indexOfObject çok daha sık kullanılacak ve sadece "zayıf" kodlama tarzı değil NSInteger ile bir for-loop şişirme saçmalık olduğunu düşünüyorum. Yalnızca indexOfObject'i izlemeli ve orada NSInteger'ları kullandığınızdan emin olmalısınız, özellikle bir şey sayılan her şey int gibi iyi, özellikle de yöntem odakları içinde
NikkyD

5

Proje> Yapı Ayarı "tuşunu değiştir" printf / scanf için arama kontrolleri : HAYIR "

Açıklama: [Nasıl çalışır]

Sağlanan bağımsız değişkenlerin belirtilen biçim dizesine uygun türlere sahip olduğundan ve biçim dizesinde belirtilen dönüşümlerin anlamlı olduğundan emin olmak için printf ve scanf vb. Çağrılarını kontrol edin.

Umarım işe yarar

Diğer uyarı

hedef c örtük dönüştürme 'NSUInteger' ('unsigned long' olarak da bilinir) 'int' tamsayı hassasiyetini kaybeder

Anahtar " örtük dönüşümü 32 Bit Türü> Hata Ayıkla> * 64 mimarisi olarak değiştir: Hayır "

[ Dikkat: 64 Bit mimari dönüşümü hakkındaki diğer uyarıları geçersiz kılabilir] .


32 bit kitaplığınızı 64 bit'e dönüştürmek istiyorsanız, bu umut verici bir seçenektir.
San

2

"İnt" için expicit döküm yapmak benim durumumda sorunu çözer. Aynı sorunu yaşadım. Yani:

int count = (int)[myColors count];

ya da "örtük" olarak mı adlandırılır? LOL :) Her iki durumda da işe yaradı.
Vladimir Despotovic
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.