• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    해결됨

printf

22.02.13 17:34 작성 조회수 292

1

좋은 강의 감사드립니다.
제가 이해한 바로는 결국 형식지정자를 사용할 때에 stack의 크기와 맞아야 하고 자료형이 맞아야 올바르게 printf가 작동한다..인데요
 
출력하려는 데이터의 크기와 형식 지정자의 사이즈가 완전 정확히 일치해야하나요?
 
1. 형식지정자가 더 크면 안되나요?
 
printf("%d", INT_MAX) => 2147483648

printf("%lld", INT_MAX) => 71230913765179391

혹은

printf("%lld", 3)=>3이 아닌 다른 숫자...

이 경우에는 lld가 INT_MAX나 숫자 3의 크기보다 더 과하게 읽어내서 그런지 숫자가 이상해지는데 이때는 왜 이런 숫자가 나오나요? INT_MAX라는 데이터의 스택을 읽기에 과한 형식 지정자여서 그런가요?????

 

 

2.printf("%hhd, %u\n", INT_MAX , INT_MAX );

의 결과값으로 0, 2147483648 두 숫자가 나오는데요,

INT_MAX가 stack에서 4byte를 차지할 것 같은데요

%hhd는 1byte를 읽어낼 것 같은데 그렇게 되면 강의해서 말씀하신 원리대로 밀리는바람에 뒤에있는 수도 정상적으로 출력되면 안되지 않나요?

총 8byte라는 스택에서 hhd(1byte) u (4byte)를 읽어내니 뒤에숫자도 정상적으로 출력되면 안될 것 같은데 이 경우엔 정상적인 값이 나오더라구요...왜그런지 궁금합니다.!!!

 

 

 

답변 1

답변을 작성해보세요.

1

강민철님의 프로필

강민철

2022.02.14

안녕하세요 :)

1. 

형식 지정자는 말 그대로 "어떻게 출력할 것인지"를 나타냅니다.

데이터를 원하는 형식에 맞게 출력하려면

출력하려는 데이터 형식과 형식 지정자의 종류가 맞아야 합니다.

(출력하려는 데이터 타입과 형식 지정자의 종류가 맞지 않으면 질문자님의 질문처럼 엉뚱한 값이 출력될 수 있습니다, 말씀하신대로 읽어야 하는 크기와 읽은 크기가 다르기 때문입니다) 

마치 질문자님의 예시처럼 아래 첫 번째 코드는 3이 아닌 엉뚱한 수가 나오지만 두 번째 코드는 long long int 형식에 맞게 출력이 되는 것처럼요

 

	printf("%lld\n", 3);
	printf("%lld\n", 3LL);

 

2. 

음.. 우선 아래 코드의 결과를 확인해보셔야 할 듯 합니다.

제 경우에는, 0, 2147483648가 아닌, -1, 2147483648이 나오거든요.

printf("%hhd, %u\n", INT_MAX , INT_MAX );

컴파일러를 바꿔 해보아도 마찬가지입니다, 

$ cat main.c
#include <stdio.h>
#include <limits.h>

int main()
{
        printf("%hhd %u\n", INT_MAX, INT_MAX);
        return 0;
}
$ gcc main.c
$ ./a.out
-1 2147483647
$

 

이건 제 추측입니다만, 

%hdd (혹은 %c) 와 같은 형식으로 INT_MAX을 출력하려고 들면

애초에 컴파일러가 이 인자에 대해서는 출력을 하지 않아버리거나,

출력이 안되게끔 C언어가 설계된 것으로 보입니다..

 

가령 아래 코드의 경우에는 결과가 2147483647, 

printf("%u\n", INT_MAX); 

아래 코드의 경우에도 결과가 2147483647이 나오기 때문입니다. 

printf("%c %u\n", INT_MAX, INT_MAX); 

질문 주신 아래 코드처럼 두 번째 INT_MAX는 멀쩡히 출력이 됩니다. 

printf("%hhd, %u\n", INT_MAX , INT_MAX );

 

그런데 이를 %f 처럼 실수형으로 출력하려고 들면 두 번째 인자에서도 영향을 받습니다.

가령 아래 코드의 경우 실행 결과는 nan 5313332 입니다.

printf("%f %u\n", INT_MAX, INT_MAX); 

 

요는,  형식을 맞추지 않을 경우 그대로 출력을 하여 두 번째 인자에도 영향이 가는 형식 지정자(%d, %f)도 있는 반면,

출력 불가능으로 판정을 내리고 곧바로 다음 인자를 출력하는 형식 지정자(%c, %hhd)도 있는 듯 보입니다.

 

정말 좋은 질문이었던 것 같습니다.

다만,  이 문제를 너무 깊이 파고들 필요는 없어 보입니다.

어차피 이렇게 형식에 맞지 않게 출력하는 경우는 없을 뿐더러, 

일부 컴파일러 (gcc)의 경우, 형식을 맞추지 않으면 애초에 컴파일이 불가능하기 때문입니다.

$ gcc main.c
main.c: In function ‘main’:
main.c:10:11: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]
  printf("%f %u\n", INT_MAX, INT_MAX);
          ~^
          %d
$

 

감사합니다.

 

정말 감사합니다!

선생님 복습하다가 질문이 더 생겼는데요

 

 

float b = 2.7f;
printf("%d, %f\n", b, b);
를 실행했더니

-1610612736, -0.000000
라는 터무니 없는 숫자 두 개가 나왔는데요..
둘을 따로 출력하니 뒤에 %f로 출력하는 숫자는 제대로 출력이 되던데
한꺼번에 쓰면 왜 앞의 숫자를 읽는 과정이 뒤에 숫자를 읽는 과정에 영향을 주는지 이해가 잘 안갑니다 ㅠ

b 자체가 float 타입이라 4byte일 것이고
%d %f 모두 4byte의 숫자를 읽어내므로 데이터의 크기는 딱 맞게 읽어내는 것 같은데요
그럼 %d로 b를 출력하는 경우는 데이터 타입이 다르므로 이상하게 출력이 된다고 쳐도
그 뒤의 %f는 앞에서 잘못 읽은 것과는 상관 없이 2.7이 나와야 하는 것 아닌가요?

즉 변환 지정자의 크기가 알맞게 할당될 경우 앞에서 데이터 타입이 달라 잘못 출력되었더라도 뒤에 알맞게 맞춰진 변환 지정자와 데이터는 출력되어야 하지 않나요?