[objective-c] 왜 형식 인수로 NSInteger 변수를 캐스트해야합니까?

NSInteger myInt = 1804809223;
NSLog(@"%i", myInt); <==== 

위의 코드는 오류를 생성합니다 :

‘NSInteger’유형의 값을 형식 인수로 사용해서는 안됩니다. 대신 ‘long’에 명시 적 캐스트를 추가하십시오.

수정 된 NSLog메시지는 실제로 NSLog(@"%lg", (long) myInt);입니다. 왜의 정수 값으로 변환해야합니까 myInt에를 long내가 디스플레이 값을 원한다면?



답변

해당 플랫폼 에서 64 비트 정수 NSInteger로 정의되고 OS X (64 비트)에서 컴파일하는 경우이 경고가 표시됩니다 long. %i위한 포맷은, 다른 한편으로는, 인 int32 비트이다. 따라서 형식과 실제 매개 변수의 크기가 일치하지 않습니다.

이후 NSInteger32 비트 또는 64 비트 인, 플랫폼에 따라 컴파일러에 캐스팅 추가 권장 long일반적.

업데이트 : iOS 7은 이제 64 비트도 지원하므로 iOS를 컴파일 할 때 동일한 경고가 표시 될 수 있습니다.


답변

형식 지정자가 데이터 유형과 일치하면 아무 것도 캐스트 할 필요가 없습니다. NSInteger기본 유형으로 정의되는 방법에 대한 자세한 내용은 Martin R의 답변을 참조하십시오 .

따라서 64 비트 환경 용으로 작성된 코드의 경우 다음과 같이 로그 문을 작성할 수 있습니다.

NSLog(@"%ld",  myInt); 

32 비트 환경에서는 다음과 같이 작성할 수 있습니다.

NSLog(@"%d",  myInt); 

캐스트없이 모두 작동합니다.

어쨌든 캐스트를 사용하는 한 가지 이유는 좋은 코드가 여러 플랫폼에 포팅되는 경향이 있기 때문에 변수를 명시 적으로 캐스팅하면 32 및 64 비트 모두에서 깨끗하게 컴파일됩니다.

NSLog(@"%ld",  (long)myInt);

그리고 이것은 결국 디버깅 보조 도구 인 NSLog 문뿐만 아니라 [NSString stringWithFormat:]프로덕션 코드의 합법적 인 요소 인 다양한 파생 메시지에도 적용됩니다.


답변

NSInteger를 NSLog로 전달하는 대신 NSNumber 만 전달하십시오. 이것은 모든 캐스트를 둘러보고 올바른 문자열 형식 지정자를 선택합니다.

NSNumber foo = @9000;
NSLog(@"foo: %@", foo);
NSInteger bar = 9001;
NSLog(@"bar: %@", @(bar));

NSUIntegers에서도 걱정할 필요가 없습니다. 혼합 64 비트 / 32 비트 환경에서 NSInteger 및 NSUInteger에 대한 답변보기


답변

를 사용하는 동안 경고는 유지 NSLog(@"%ld", (long)myInt);하지만 long myInt = 1804809223;iOS 10에서 변경 선언 후 경고를 중지합니다 .


답변

OS X은 NSInteger, NSUInteger, CGFloat 및 CFIndex와 같은 여러 데이터 유형을 사용하여 32 비트 및 64 비트 환경에서 일관된 값을 나타내는 수단을 제공합니다. 32 비트 환경에서 NSInteger 및 NSUInteger는 각각 int 및 unsigned int로 정의됩니다. 64 비트 환경에서 NSInteger 및 NSUInteger는 각각 long 및 unsigned long으로 정의됩니다. 플랫폼에 따라 다른 printf 스타일 유형 지정자를 사용할 필요가 없도록 이 링크 에 표시된 지정자를 32 비트 및 64 비트 환경 모두 에 사용할 수 있습니다 .


답변