인프런 커뮤니티 질문&답변

이호영님의 프로필 이미지
이호영

작성한 질문수

홍정모의 따라하며 배우는 C언어

3.7 다양한 정수형들

형식지정자 크기와 자료형에 대한 질문입니다.

해결된 질문

작성

·

381

0

#include <stdio.h>

#include <limits.h>

#include <stdlib.h>

int main()

{

char c = 65;

short s = 200;

unsigned int ui = 3000000000U;

long l = 65537L;

long long ll = 12345678908642LL;

printf("char = %hhd, %d, %c, %ld, %lld\n", c, c, c, c, c); // 왜 %lld 만 수가 다르게 나오나요? 분명 더 큰 형식지정자인데 궁금합니다.

printf("short = %hhd, %hd, %d, %ld, %lld\n", s, s, s, s, s);

printf("unsigned int = %u, %d\n",ui,ui);

printf("long = %ld, %hd, %lld\n", l, l, l);

printf("long long = %lld, %ld\n",ll,ll);

return 0;

}

질문: 더 큰 형식지정자인 %lld 를 사용해서 char 자료형을 출력했는데 다른 형식지정자들은 65로 같게 나오는데 %lld 만 다르게 출력됩니다. 무슨 이유가 있나요?

답변 1

6

**100% 정확한 설명이 아닐 수 있습니다. 오류 발견 시 지적 부탁드립니다.**

먼저 format specifier 는 변수를 어떻게 읽어낼 것인지 알려주는 parameter 입니다. 즉, %lld는 char c를 long long int 처럼 읽어내겠다는 뜻이지, char c 가 long long int 가 되는 것이 아닙니다. 따라서 위의 코드에서 c를 long long int 로 캐스팅 하고 %lld로 읽어내면 해당 문제가 사라집니다

아래의 내용은 조금 더 심화된 설명입니다 ( 참고한 글 https://operatingsystems.tistory.com/entry/Kernel-printf-%ED%95%A8%EC%88%98

뒷부분 함수, 포인터 등의 강의를 듣고 다시 읽으시면 조금 더 이해되실 것 같습니다

첫 줄만 실행했을 때의 결과값입니다

디버거에서 해당되는 메모리를 읽었을 때의 캡쳐 사진입니다

이 내용을 이해하시려면 스택에 대한 이해가 필요한데

현재 메모리의 스택에 c, s ui, l, ll 이 쌓여있습니다. c는 char 자료형으로 1 byte를 사용하고, 16진수로 표현된 c의 아스키 코드 값은 41입니다.

그리고 문제의 %lld의 쓰레기값이 나오는 부분이 별표 친 부분입니다

상단에 첨부해드린 제 결과값을 보시면, %lld로 출력했을 때의 십진수 값은 14,094,884,369,596,481입니다

이를 16진수로 바꾸면 0032 1339 0000 0041 이고, 그게 바로 별표 친 부분의 값입니다

그럼 왜 이러한 문제가 발생하느냐

여기서부터는 사실과 추측이 섞인 답변이니, 참고하시고 받아들이시기 바랍니다

별표친 부분의 우측에 ?가 가득한 창을 보시면, A가 여러 번 적혀있는 것을 알 수 있습니다. 이는 c의 값인 65로서, printf가 호출되며 함께 호출된 것입니다.

자세한 이유는 모르겠으나, A... 5번 반복되는 것으로 보아, char, short 할 것 없이 모두 4byte 씩 공간을 차지하고 있습니다

(printf 에서 스택에 주소값을 올리는 것과, x64에서는 A.......으로 8byte를 갖는 것으로 추측해보면, 주소의 크기만큼 공간을 차지하는 것으로 보입니다)

이때 마지막에 %lld로 읽어들이면, 실제 변수가 갖는 값보다 더 큰 공간을 읽어들이게 됩니다. 이때 garbage value 가 출력되는 것입니다.

(printf 내에서 %lld를 맨 앞으로 옮겨보면, 맨 마지막의 format specifier 에서도 데이터가 밀리는 오류가 발생함을 알 수 있습니다. 이때의 값은 10진수로 279,172,874,305이 출력되는데 16진수 값으로는 A가 존재하는 4byte 공간 두개를 붙인 0000 0041 0000 0041 임을 알 수 있습니다.)

정리하자면, 이런 문제가 발생하는 것은 %lld가 변수를 읽어내는 방식에 불과하기 때문입니다. 실제 변수가 차지하는 공간보다 큰 공간을 읽어들이기 때문에 문제가 발생합니다.

-답변이 도움이 되셨다면 좋아요를 눌러주세요!-

이호영님의 프로필 이미지
이호영

작성한 질문수

질문하기