NSLOG (…) 부적절한 형식 지정자는 다른 변수에 영향을 미치나요?
-
22-07-2019 - |
문제
나는 최근 NSLOG 에서이 이상한 행동을 추적하는 약 30 분 동안 낭비했다.
NSString *text = @"abc";
long long num = 123;
NSLog(@"num=%lld, text=%@",num,text); //(A)
NSLog(@"num=%d, text=%@",num,text); //(B)
줄 (a)는 "num = 123, text = abc"를 인쇄하지만 (b) 라인 (b) "num = 123, text =를 인쇄합니다.(없는)".
분명히 인쇄 a long long
~와 함께 %d
실수이지만 누군가가 왜 그런 원인을 설명 할 수 있습니까? text
NULL로 인쇄하려면?
해결책
스택에서 메모리 정렬을 엉망으로 만들었습니다. X86 프로세서가있는 최신 Apple 제품을 사용하는 것보다 가정합니다. 이러한 가정을 고려하여 스택을 고려하여 두 상황 모두에서 마치 다음과 같습니다.
| stack | first | second | +---------------------+-------+--------+ | 123 | | %d | +---------------------+ %lld +--------+ | 0 | | %@ | +---------------------+-------+--------+ | pointer to text | %@ |ignored | +---------------------+-------+--------+
첫 번째 상황에서는 스택 8 바이트와 4 바이트를 입습니다. 그리고 NSLOG보다 스택 12 바이트 (8 바이트 %lld
그리고 4 바이트 %@
).
두 번째 상황에서는 NSLOG에게 먼저 4 바이트를 가져 오도록 지시합니다 (%d
). 변수는 8 바이트 길이이고 실제로 적은 숫자를 보유하기 때문에 상위 4 바이트는 0이됩니다. 그러면 NSLOG가 텍스트를 인쇄하려고 할 때 nil
스택에서.
메시지를 보내는 이후 nil
OBJ-C에서 유효합니다 NSLOG는 방금 보내집니다 description:
에게 nil
아마 아무것도 얻지 못한 다음 인쇄 (null).
결국 Objective-C는 추가로 C이기 때문에 발신자는이 혼란을 정리합니다.
다른 팁
Varargs가 구현되는 방법은 시스템 의존적입니다. 그러나 발생하는 것은 논쟁이 크기가 다를 수 있지만 인수는 버퍼에 연속적으로 저장된다는 것입니다. 그래서 처음 8 바이트 (그것이 크기라고 가정합니다. long long int
논쟁의)는이다 long long int
, 그리고 다음 4 바이트 (시스템의 포인터 크기라고 가정)는 다음과 같습니다. NSString
바늘.
그런 다음 함수를 기대할 때 int
그리고 포인터는 처음 4 바이트가 int
(그것이 크기라고 가정합니다 int
) 그리고 다음 4 바이트는 포인터가 될 것입니다. 귀하의 시스템에 대한 논쟁의 특정 엔지니어와 배열로 인해 long long int
숫자의 가장 중요한 바이트가되므로 123 인쇄를 인쇄합니다. 그런 다음 객체 포인터의 경우 다음 4 바이트를 읽습니다. a로 해석되었습니다 nil
바늘. 실제 포인터는 결코 읽지 않습니다.