가변인자 함수 관련

5417 단어 c언어c언어

intro

char a = 3;
printf("%d", a);

어째서 위와 같은 코드는 동작하는 것일까?

상식적으로 생각해 보면 FSF로 %d를 사용하였으니까 sizeof(int) 만큼(통상 4byte 만큼) 읽어올 것이고, 그래서 char 형인 a가 주어졌으니까 오류가 날 것처럼 보인다.

그러나 저 코드는 100% 정상 작동하는 아주아주 적법한 코드이다.

왜 그런 것일까? 이는 가변인자 함수가 굴러가는 방식과 밀접한 관련이 있다.

가변인자? 가변인자!

printf같은, 이미 표준 라이브러리에 구현된 가변인자 함수를 써 본 경험이야 다들 몇 번 있을 것이다.

그러나 직접 가변인자를 받는 함수를 만들어 본 적은 거의 없을 것이라고 생각한다. 사실 가변인자 함수를 새로 만드는걸 권장하지도 않는다.

왜냐하면, 생각보다 쓸 일이 별로 없고, 비효율적이고, 버그가 생기기도 쉽기 때문이다.

아마 가변인자 함수가 어떤 식으로 처리되는지 보면 바로 감이 올 것이다.

왜 쓰레기인가

/* 적당한 가변인자 함수*/
int var_arg_test(const char *format, ...) 
{
    va_list va; // 가변인자들이 싹 다 들어있는 리스트
    va_start(va, format);
    double a = va_arg(va, double); // 타입에 맞춰서 읽어옴.
    /*...적당히 섹시한 코드...*/    
    va_end(va);
}
/*이후 생략*/

뭐가 뭔지는 대충 알거라고 생각하고, 왜 쓰레기인지만 간단하게 설명하도록 하겠다.

  • 쓰레기인 이유 1

주목해야 할 것이 저어기 저 va_arg(va, double) 부분이다. 읽는 쪽에서 타입을 지정해야 한다는, 다소 충격적인 사실을 알 수 있다.

무슨 void*도 아니고... va_list에 들어있는 가변인자들은 타입관련 정보가 날아가버린 상태다. 심지어 va_list에 가변인자가 몇 개나 들어있는지도 모른다.

그냥 va_arg를 사용해서 타입 맞춰서 읽어오는게 끝이다. 받는 쪽에서 알아서 타입을 맞춰서 읽어와야된다는게 얼마나 개떡같은 구현인지는 말 안해도 알거라고 생각한다.

그리고 왜 format specifier를 쓰는지, 왜 칼같이 format specifier를 맞춰야 하는지에 대해서도 알게 되었을 것이다.

거기 말고는 인자들 정보를 읽어올 데가 없으니까...

  • 쓰레기인 이유 2

그 다음으로 쓰레기 같은 부분은, default argument promotion이랑 깊은 연관이 있다.

대에충 가변인자함수의 가변인자로 밀려들어간 인자들에게 일어나는 기묘한 현상이다.

char c = 3;
short d = 12;
printf("%d %d", c, d);

머 이런 코드가 있다고 할 때, 주는 쪽에서는 분명이 short하나랑 char하나를 넘겼다고 생각하는데...

실제로는 int형 2개로 진급(promotion)되서 전달된다.(일반적으로 그렇다는거고 뭐... 굳이 자세하게 적자면 산술 연산에서 일어나는 정수진급이랑 동일한 규칙을 따른다.)

추가로 float를 넘기는 경우에도 double로 승급되서 전달된다.

아까 비효율이 어쩌고 했던거도 이런 기묘한 특성 때문이다.

unsigned char c = 'a';
printf("%hhu\n", c);

ㄴ 위 코드 처럼 쓰면 cint로 승급해서 전달된 다음에 다시 unsigned char로 형변환을 거쳐서 화면에 출력되게 된다. ㅈㄴ 비직관적이고 비효율적이다.

그건 그렇고 이제 왜 %dchar형 변수를 출력할 수 있는지 알게 되었을 것이다.


사족

왜 이딴 일이 생기는지, 그리고 왜 가변인자 함수에서만 그러는지는 음... 옛날 옛적 C언어의 잔재라고 하겠다.

사실 가변인자 함수 말고 다른 함수에서도 일어날 수 있는 일이기는 한데... 대가리가 정위치에 놓여있는 인간이면 자기 손으로 그런 코드를 만들 일은 절대 없을거니가 뭐...

그런 시시콜콜한 것까지 자세히 설명하는건 너무 귀찮으니까, 정 궁금하면 찾아보든가 계속 궁금한 채로 살든가 하십셔.

차피 똑똑한 놈들은 이 글 안봐도 뭐 다 알고 있었을거고...

걍 개인적으로 정리하는 차원에서 써봤음.


좋은 웹페이지 즐겨찾기