C언어

[C 언어] printf 파헤치기

Teodore 2023. 1. 8. 19:53
728x90

C언어를 하는 사람치고 printf를 한번도 안쓴 사람은 없다.
그런데 printf를 제대로 아는 사람은 별로 없을 것이라 생각한다.
2가지 중요한 포인트가 있어 설명하려고 한다.

1. Format 문자열의 이해

먼저 아래 코드를 보면,

1
2
3
4
5
6
7
int main(void)
{
    printf("Hello World!\n");
    printf("Hello"" ""World!\n");
    return 0;
}
 
cs

 

위 코드의 첫째줄은 흔히 사용하는 방식, 두번째 줄은 잘 사용하지 않는 방식이지만 정상적인 코드다.
물론 두줄의 코드 모두 "Hello World!"를 출력하게 된다.

이것에 대해 왜 이렇게 동작하는지 이해할 필요가 있다.
printf의 원형을 보면

1
printf(char const* const _Format, ...)
cs

 

위와 같이 _Format과 ...으로 이루어져 있다. Format은 char* 형태이므로
문자열을 의미하게 되고, C 표준을 기준으로 보면 연속된 " "의 구문은 하나의 " "으로 묶어서 해석될 수 있다.
즉, 위의 코드에서 " "으로 감싸진 문자열이 몇개가 되든 사이 공백을 무시하고 하나의 문자열로 인식된다.

2. ... 인수

Format 인수 옆의 ...은 가변 인수로서 함수의 인수의 개수 제한을 두지 않는 형식이다.

1
2
3
4
printf("%d", a);
printf("%d %d", a, b);
printf("%s %x %d", str, h, a);
 
cs

위와 같이 printf에는 여러가지 형식이 포함된 Format과 그에 맞는 여러 인수가 들어갈 수 있다.
이것을 가능하게 하는 것이 ... 변수이고 이것의 동작 방식은 Stack을 이해하면 가능하다.
함수가 호출될 때 Stack 메모리가 쌓이게 되고 함수의 인자들이 여기에 들어간다.
즉, printf는 맨 앞의 Format을 기준으로 해석되기 시작하면서 Format안의 연산자 %d, %f, %c, %s등에 의해
필요시 stack의 다음 포인터의 메모리를 가져온다.
정리하면 printf("%d",a,b,c,d);나 printf("%s, %c, %d"); 는 에러를 내지 않는 구문이다.
물론 원하는 결과는 나오지 않기 때문에 개발시 실수하지 않도록 주의해야 되는 점이다.

728x90