การแปลงโดยนัยของ Objective-C สูญเสียความแม่นยำจำนวนเต็ม 'NSUInteger' (หรือที่รู้จักว่า 'ไม่ได้ลงนามยาว') เป็นคำเตือน 'int'


187

ฉันทำงานผ่านแบบฝึกหัดและได้รับคำเตือนว่า:

การแปลงโดยนัยสูญเสียความแม่นยำของจำนวนเต็ม: 'NSUInteger' (aka 'long 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;
}

ภาพหน้าจอ

คำตอบ:


470

countวิธีการในการNSArrayส่งกลับNSUIntegerและ 64 บิตแพลตฟอร์ม OS X

  • NSUIntegerถูกกำหนดให้เป็นunsigned longและ
  • unsigned long เป็นจำนวนเต็ม 64 บิตที่ไม่ได้ลงชื่อ
  • int เป็นจำนวนเต็ม 32 บิต

ดังนั้นintเป็นประเภทข้อมูล "เล็ก" กว่าNSUIntegerดังนั้นคำเตือนคอมไพเลอร์

ดูNSUIntegerใน "การอ้างอิงชนิดข้อมูลพื้นฐาน":

เมื่อสร้างแอ็พพลิเคชัน 32 บิต NSUInteger เป็นจำนวนเต็มแบบ 32 บิตที่ไม่ได้ลงชื่อ แอปพลิเคชัน 64 บิตถือว่า NSUInteger เป็นจำนวนเต็ม 64 บิตที่ไม่ได้ลงชื่อ

ในการแก้ไขคำเตือนของคอมไพเลอร์นั้นคุณสามารถประกาศcountตัวแปรโลคัลเป็น

NSUInteger count;

หรือ (ถ้าคุณแน่ใจว่าอาร์เรย์ของคุณจะไม่มี2^31-1องค์ประกอบมากกว่านี้!) ให้เพิ่มนักแสดงที่ชัดเจน:

int count = (int)[myColors count];

19
เพียงเพิ่ม - ฉันโหวตคำตอบนี้เมื่อฉันได้รับคำเตือนและข้อผิดพลาดทั้งหมดในโปรเจ็กต์ Xcode 5 ของฉัน คุณพูดถึง 64 บิตซึ่งทำให้ฉันมองไปที่การตั้งค่าการสร้างของฉัน Xcode เปลี่ยนเป็นโหมด 64 บิตซึ่งทำให้เกิดข้อผิดพลาดขึ้น การเปลี่ยนกลับเป็น arvm7 ได้แก้ไขทั้งหมดแล้ว
Robert J. Clegg

1
@Tander มีความแตกต่างระหว่างการรวบรวม 64 บิตกับ armv7 หรือไม่?
Shaun Budhram

1
@ShaunBudhram โดยลักษณะของมันไม่ ฉันไม่เห็นความแตกต่าง มันจะสร้างความแตกต่างในแอพที่ใช้ CPU อย่างหนักเท่านั้นตัวอย่างเช่นเกมจะได้รับประโยชน์จากการรวบรวม 64 บิต
Robert J. Clegg

7
"เริ่มตั้งแต่วันที่ 1 กุมภาพันธ์ 2015 แอป iOS ใหม่ที่อัปโหลดไปยัง App Store จะต้องมีการสนับสนุน 64 บิต ... " - ข่าวและการอัพเดทสำหรับนักพัฒนา Apple, 20 ตุลาคม 2014
Pang

2
@JayprakashDubey: Apple ไม่เห็นคำเตือนคอมไพเลอร์ของคุณเพราะคุณส่งแอปพลิเคชันที่คอมไพล์แบบไบนารีไปยัง App Store ดังนั้นแอปของคุณจึงไม่สามารถปฏิเสธได้เนื่องจากคำเตือนของคอมไพเลอร์ แน่นอนคุณควรแก้ไขให้แอปของคุณทำงานได้อย่างถูกต้อง
Martin R

24

ตรงกันข้ามกับคำตอบของ Martin การส่งไปที่ int (หรือเพิกเฉยต่อคำเตือน) จะไม่ปลอดภัยเสมอไปแม้ว่าคุณจะรู้ว่าอาร์เรย์ของคุณไม่มีองค์ประกอบมากกว่า 2 ^ 31-1 ไม่ใช่เมื่อรวบรวมเป็น 64 บิต

ตัวอย่างเช่น:

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
คุณพูดถูกแล้วว่าผลลัพธ์ที่indexOfObject:ได้นั้นเป็นความคิดที่ไม่ดี คำตอบของฉันมีความหมายสำหรับรหัสเฉพาะในคำถามและวิธีการที่ไม่สามารถกลับcount NSNotFoundฉันไม่แนะนำให้ส่งไปยัง int หรือเพิกเฉยต่อคำเตือนโดยทั่วไป ขออภัยถ้ามันไม่ชัดเจน ในความเป็นจริงรหัสตัวอย่างของคุณจะสร้างคำเตือนที่if (i == NSNotFound)หากรวบรวมเป็น 64 บิตดังนั้นปัญหาจะไม่ถูกสังเกต
Martin R

@ เอเดรีย: ถ้าคุณไม่รังเกียจคุณจะแนะนำสิ่งที่ผู้ถามทำอย่างไร
moonman239

@ moonman239 โดยทั่วไปแล้วฉันจะใช้ตัวแปรประเภทที่ถูกต้องถ้าเป็นไปได้ (@ ข้อเสนอแนะครั้งแรกของ @ MartinR) เมื่อเทียบกับการคัดเลือกนักแสดง (ที่สองของเขา) ในขณะที่เขาชี้ให้เห็นการคัดเลือกนักแสดงมีความปลอดภัยในกรณีนี้โดยเฉพาะ แต่ฉันคิดว่ามันเป็นนิสัยที่ไม่ดีพอที่จะเข้าไปเพราะมันอาจมีผลกระทบที่ไม่คาดคิด ฉันโพสต์เพราะฉันถูกกัดโดยสถานการณ์เฉพาะนี้ (แม้ว่าจะเป็นจุดที่ดีเกี่ยวกับคำเตือนคอมไพเลอร์ == ซึ่งฉันต้องพลาด)
เอเดรียน

2
ฉันคิดว่าการนับจะถูกใช้บ่อยกว่า indexOfObject และ bloating for-loop กับ NSInteger เพียงเพื่อไม่ให้มีรูปแบบการเข้ารหัส "ไม่ดี" เป็นเรื่องไร้สาระ คุณควรจะดู แต่เพียงผู้เดียวสำหรับ indexOfObject และให้แน่ใจว่าคุณใช้ NSIntegers มีทุกอย่างที่ก็นับเป็นสิ่งที่ดีเช่น int โดยเฉพาะในวิธีการมุ่งเน้น
NikkyD

5

เปลี่ยนคีย์ในโครงการ> สร้างการตั้งค่า "การเรียก typecheck ไปยัง printf / scanf : NO "

คำอธิบาย: [มันทำงานอย่างไร]

ตรวจสอบการโทรไปที่ printf และ scanf ฯลฯ เพื่อให้แน่ใจว่าอาร์กิวเมนต์ที่ให้นั้นมีประเภทที่เหมาะสมกับสตริงรูปแบบที่ระบุและการแปลงที่ระบุในสตริงรูปแบบเหมาะสม

หวังว่ามันจะทำงาน

คำเตือนอื่น ๆ

การแปลงโดยนัย c การสูญเสียความแม่นยำจำนวนเต็ม 'NSUInteger' (aka 'unsigned long') เป็น 'int

เปลี่ยนคีย์ " การแปลงโดยนัยเป็นประเภท 32 บิต> ตรวจแก้จุดบกพร่อง> * สถาปัตยกรรม 64: ไม่ "

[ ข้อควรระวัง:มันอาจเป็นโมฆะเตือนอื่น ๆ ของการแปลงสถาปัตยกรรม 64 บิต]


หากคุณต้องการแปลงไลบรารี่ 32 บิตของคุณเป็น 64 บิตนี่เป็นตัวเลือกที่น่าสนใจ
San

2

การชี้ขาดอย่างชัดเจนไปที่ "int" ช่วยแก้ปัญหาในกรณีของฉัน ฉันมีปัญหาเดียวกัน ดังนั้น:

int count = (int)[myColors count];

หรือเรียกว่า "นัย" ฮ่า ๆ :) ไม่ว่าในกรณีใดมันก็ใช้ได้
Vladimir Despotovic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.