NSInteger→long의 캐스트에 대해 생각한다

7461 단어 XcodeiOSObjective-C

소개



나는 hoge라는 NSInteger 변수의 값을 기록 할 때,
NSInteger hoge = 100;
NSLog(@"output hoge = %ld", (long)hoge);

같은 코드를 작성했습니다.
NSString에서 NSInteger의 변수 값을 처리하는 경우,
NSInteger hoge = 100;
NSString *hogeString = [NSString stringWithFormat:@"%ld", (long)hoge];

같은 느낌이군요.

이 long에 캐스팅하는 코드의 경우,
NSNumber를 사용하거나 or 형식 지정자를 %zd로 만들자고 전날 가르쳤습니다.
(본 기사에서는 NSNumber에 대해서는 특별히 언급하지 않습니다.)

원래 왜 NSInteger는 long에 캐스팅해야했던 것일까-라는 것을 포함해 정리합니다.

NSInteger의 값을 기록해 봅니다.



1.NSInteger의 값을 지정자 %d로 로그 출력


NSInteger hoge = 100;
NSLog(@"output hoge = %d", hoge);

caseA. iPhone5 이전의 단말(and iPhone5c)
→ 화내지 않는다.


caseB. iPhone5s 이후의 단말
→ 화난다.


지정자 %d를 사용한 경우,
32비트 단말에서는 화나지 않지만 64bit 단말에서는 화가
그렇군요.

2.NSInteger의 값을 지정자 %ld로 로그 출력


NSInteger hoge = 100;
NSLog(@"output hoge = %ld", hoge);

caseA. iPhone5 이전의 단말(and iPhone5c)
→ 화난다.


caseB. iPhone5s 이후의 단말
→ 화내지 않는다.


지정자 %ld를 사용한 경우,
32비트 단말에서는 화나지만 64bit 단말에서는 화나지 않는다
그렇군요.

1.%d를 사용한 경우와 2.%ld를 사용한 경우 모두
"인수에 NSInteger를 사용해서는 안됩니다. 명시 적으로 long으로 캐스트해야합니다."
라는 경고가 나옵니다.
경고대로 long에 캐스팅해 주면 32bit 단말에서도 64bit 단말에서도 화를 내지 않습니다.


경고의 의미를 탐구



경고의 의미를 찾기 위해 NSInteger가 어떤 녀석인지 들여다 보았습니다.


32bit의 경우,
typedef int NSInteger;
typedef unsigned int NSUInteger;

64bit의 경우,
typedef long NSInteger;
typedef unsigned long NSUInteger;

라는 정의였습니다.

방금 확인한 경고는
32bit 단말, 64bit 단말에서는 NSInteger의 정의가 다르기 때문에 발생하고 있었다
그렇군요.

길고 현실적으로 사용하는 것은 없지만,
다음과 같이 쓰면 32bit 단말, 64bit 단말 모두
경고 없이, 로그 출력할 수 있었습니다.
NSInteger hoge = 100;

#ifdef __LP64__
    NSLog(@"[64bit] output hoge = %ld", hoge);
#else
    NSLog(@"[32bit] output hoge = %d", hoge);
#endif

형식 %zd에서 32bit, 64bit 모두 지원



경고의 원인은 밝혀졌습니다.
계속해서, 명시적으로 캐스트 하지 않아도 32bit, 64bit 양쪽에 대응할 수 있다고 하는 %zd과는 누구인가 정리해 보겠습니다.

%zd은
지정자 %d(부호 첨부 32bit 정수)에
길이 한정자 z (size_t 또는 이와 유사한 부호있는 정수임을 지정)
를 붙인 것입니다.
( 문자열 조작 프로그래밍 가이드 의 p16~ 당을 ​​참고로 했습니다.)

size_t는 녀석,
(size_t)sizeof(NSInteger)

이런 느낌으로 얻을 수 있는 메모리 크기입니다.

NSInteger, int, long, size_t의 메모리 크기
sizeof( )로 보자.

caseA. 32bit 단말기


caseB. 64bit 터미널


NSInteger의 정의가 32bit 단말의 경우 int형, 64bit 단말의 경우 long형이므로,
32bit의 경우
NSInteger 메모리 크기 = int 메모리 크기 = 4
64bit의 경우
NSInteger 메모리 크기 = long 메모리 크기 = 8
이었다.

또한, 32bit의 경우, 64bit의 경우 모두
NSInteger의 메모리 크기 = size_t의 메모리 크기
라는 것을 확인할 수 있었습니다.

그래서 아래와 같이 형식 %zd을 사용하면 32bit, 64bit 양쪽 모두에 대응할 수 있다고 하는 느낌이군요.
NSInteger hoge = 100;
NSLog(@"output hoge = %zd", hoge);

사이고에게



확인한 것을 여러가지 쓰면 길어져 버렸습니다만 일단 정리할 수 있었습니다.

문자열 조작 프로그래밍 가이드
이쪽을 더 빨리 읽어 두면 좋았어-라고 생각했습니다.

좋은 웹페이지 즐겨찾기