[objective-c] NSInteger에 대한 NSLog / printf 지정자?

A NSInteger는 32 비트 플랫폼에서 32 비트이고 64 비트 플랫폼에서 64 비트입니다. NSLog의 크기와 항상 일치 하는 지정자가 NSInteger있습니까?

설정

  • Xcode 3.2.5
  • llvm 1.6 컴파일러 (이것은 중요합니다; gcc는 이것을하지 않습니다)
  • GCC_WARN_TYPECHECK_CALLS_TO_PRINTF

그로 인해 여기에 슬픔이 생겼습니다.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    @autoreleasepool {
        NSInteger i = 0;
        NSLog(@"%d", i);
    }
    return 0;
}

32 비트 코드의 %d경우 지정자가 필요 합니다. 그러나 %d지정자를 사용하면 64 비트를 컴파일 할 때 %ld대신 사용하라는 경고 메시지가 표시됩니다 .

%ld64 비트 크기를 일치시키는 데 사용 하면 32 비트 코드를 컴파일 할 때 %d대신 사용하라는 경고 메시지가 표시 됩니다.

두 경고를 한 번에 해결하려면 어떻게합니까? 어느 쪽에서 나 사용할 수있는 지정자가 있습니까?

이 또한 영향 [NSString stringWithFormat:][[NSString alloc] initWithFormat:].



답변

업데이트 된 답변 :

모든 아키텍처 에서 zt수정자를 사용하여 경고 를 처리 NSInteger하거나 NSUInteger경고없이 처리 할 수 있습니다 .

당신은 사용하고자하는 %zd서명에 대한 %tu서명을 위해, 그리고 %tx진수를 위해.

이 정보는 Greg Parker 가 제공 합니다.


원래 답변 :

공식 권장되는 방법은 사용하는 것입니다 %ld귀하의 지정자로하고,에 실제 인수를 캐스팅 long.


답변

허용되는 답변은 절대적으로 합리적이며 표준을 준수하며 정확합니다. 유일한 문제는 더 이상 작동하지 않는다는 것인데, 이는 완전히 애플의 잘못입니다.

% zd 형식은 size_t 및 ssize_t의 C / C ++ 표준 형식입니다. NSInteger 및 NSUInteger와 같이 size_t 및 ssize_t는 32 비트 시스템에서 32 비트이고 64 비트 시스템에서 64 비트입니다. 이것이 % zd를 사용하여 NSInteger와 NSUInteger를 인쇄하는 이유입니다.

그러나 NSInteger 및 NSUInteger는 64 비트 시스템에서 “long”으로 정의되고 32 비트 시스템 (64 대 32 비트)에서 “int”로 정의됩니다. 오늘날,이 size_t는 모든 시스템의 “긴”에 정의되어 있다 NSInteger (중 64 또는 32 비트)와 동일한 크기이지만 상이한 유형. Apple의 경고가 변경되었으므로 (올바른 비트 수가 있더라도 잘못된 유형을 printf에 전달할 수 없음) size_t 및 ssize_t의 기본 유형이 변경되었습니다. 어느 것을 모르지만 % zd가 얼마 전에 작동을 멈췄습니다. 현재 32 비트 및 64 비트 시스템 모두에서 NSInteger를 경고없이 인쇄하는 형식 은 없습니다 .

따라서 불행히도 할 수있는 유일한 일 : % ld를 사용하고 값을 NSInteger에서 long으로 또는 NSUInteger에서 unsigned long으로 캐스트하십시오.

더 이상 32 비트를 빌드하지 않으면 캐스트없이 % ld 만 사용할 수 있습니다.


답변

포맷터는 표준 UNIX / POSIX printf 기능에서 제공됩니다. 사용 % 루서명 오래 , 오래 %의 LD, 오래 오래 %의 LLD, 그리고 %의 LLU 에 대한 부호 오래 오래 . 콘솔에서 man printf를 시도하지만 Mac에서는 불완전합니다. 리눅스 맨 페이지는보다 명백하다 http://www.manpages.info/linux/sprintf.3.html

두 경고는 모두 NSLog (@ “% lu”, (unsigned long) arg)로만 해결할 수 있습니다. 코드가 iOS 용 32 및 64 비트로 컴파일되므로 캐스트와 결합됩니다. 그렇지 않으면 각 컴파일마다 별도의 경고가 생성됩니다.


답변