Objective-C 암시 적 변환은 정수 정밀도 'NSUInteger'(일명 '부호없는 long')를 'int'경고로 잃습니다.


187

몇 가지 연습을 진행 중이며 다음과 같은 경고가 표시됩니다.

암시 적 변환은 정수 정밀도를 잃습니다 : 'NSUInteger'(일명 '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이므로 컴파일러 경고입니다.

"Foundation Data Types Reference"의 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 그것의 외관에 의해 nope. 나는 아무런 차이도 보지 못했다. CPU를 많이 사용하는 앱에서만 차이가 생길 수 있습니다. 예를 들어 게임은 64 비트 컴파일 이점을 볼 수 있습니다.
Robert J. Clegg 2014 년

7
"2015 년 2 월 1 일부터 App Store에 업로드 된 새로운 iOS 앱에 64 비트 지원 기능이 포함되어야합니다 ..."- Apple Developer News and Updates, 2014 년 10 월 20 일
Pang

2
@JayprakashDubey : 바이너리 컴파일 된 응용 프로그램을 App Store에 제출하기 때문에 Apple에서 컴파일러 경고를 표시하지 않습니다. 따라서 컴파일러 경고로 인해 앱을 거부 할 수 없습니다. 물론 앱이 올바르게 작동하도록 수정해야합니다.
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

@Adrian : 마음에 들지 않는다면, asker는 무엇을 제안합니까?
moonman239

@ moonman239 일반적으로 캐스팅과 반대되는 가능한 한 올바른 유형의 변수 (@MartinR의 첫 번째 제안)를 사용합니다 (두 번째). 그가 지적했듯이,이 특별한 경우 캐스팅은 안전하지만 (예시와 같이) 예기치 않은 결과가 발생할 수 있기 때문에 나쁜 습관이라고 생각합니다. 이 특정 상황에 물 렸기 때문에 게시했기 때문에 (실제로 == 컴파일러 경고에 대해 좋은 지적이지만).
Adrian

2
countOfObject보다 훨씬 자주 count가 사용될 것이라고 생각하고 NSInteger로 for-loop를 부 풀리는 것은 "나쁜"코딩 스타일을 갖지 않는 것이 의미가 없습니다. indexOfObject만을 감시하고 NSIntegers를 사용하고 있는지 확인하십시오. NSIntegers를 사용하는 것이 중요합니다. 특히 메소드 초점 내에서 단순히 계산하는 모든 것이 int
로도 좋습니다.

5

프로젝트> 빌드 설정에서 키 변경 " printf / scanf에 대한 typecheck 호출 : NO "

설명 : [작동 원리]

제공된 인수에 지정된 형식 문자열에 적합한 유형이 있고 형식 문자열에 지정된 변환이 의미가 있는지 printf 및 scanf 등의 호출을 확인하십시오.

그것이 작동하기를 바랍니다

다른 경고

목적 c 내재적 변환은 정수 정밀도 'NSUInteger'(일명 'unsigned long')를 'int'로 잃습니다.

키 " 암시 적 변환을 32 비트로 변경 > 유형> 디버그> * 64 아키텍처 : 아니오 "

[ 주의 : 64 비트 아키텍처 변환에 대한 다른 경고가 무효화 될 수 있습니다] .


32 비트 라이브러리를 64 비트로 변환하려면 유망한 옵션입니다.
San

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.