42Seoul

[42Seoul] ft_printf : va_arg(), 바이트패딩에 대한 약간의 고찰

Jintiago 2022. 7. 30. 21:43

본 과제에서 익혀야 할 부분은 가변인자함수의 사용이다.

핵심은 stdargs.h 의 매크로함수들이 어떻게 동작하는 것인지 이해하는 것이라고 생각했다.

 

mandatory만 구현하니까 생각보다 금방 했다.

라피신 때 만든 함수들을 활용하니 순식간에 완성했다.

 

이해가 어려웠던 부분은 매크로함수 중 하나인 va_arg()의 작동 방식이었다.

 

이 과제에 대해 적은 다른 블로그와 이 매크로 함수에 대한 글들을 찾아봤는데, 다소 두루뭉실하게 설명이 되어 있어 이해가 어려웠다.

특히, 바이트패딩이 왜 들어가야 하는지는 알겠는데, 그걸 누가 해 주는 것인지는 찾을 수 없었다.

stdarg.h 의 매크로 함수가 해 주는 것인가? 사용자가 va_arg()에 입력한 타입에 따라 일어나게 되는 것인가?

그렇다고 보기에는, va_arg()는 그저 현재 주소에 들어 있는 값을 반환하고 포인터를 이동하는 역할 밖에 하지 않기에 데이터들은 일정 간격으로 이미 들어있던 것이라고 볼 수밖에 없다.

 

계속 헤메던 중, 사막의 오아시스 같은 글을 발견했다.

 

https://blog.naver.com/PostView.nhn?blogId=wkdghcjf1234&logNo=221738196805 

 

[C] 가변 인자 규칙과 매개변수 스택

https://cafe.naver.com/gogoomas/374035 오랜만에 고구마 카페 들어갔다가 재밌는 질문을 발견해서 또 오...

blog.naver.com

유용한 정보를 요약하자면 다음과 같다.

1) 함수의 매개변수는 32비트 환경에서는 4바이트, 64비트 환경에서는 8바이트 간격으로 배치된다.

2) 32비트 환경과 64비트 환경에서의 va_arg()에 대한 정의는 다르다.

 

즉, 바이트패딩은 함수의 인자들이 정의될 때 일어나는 것이다!

 

32비트 환경에서 가변인자로 들어온 값들은 4바이트 간격으로 배치되며, 크기가 4바이트를 초과할 경우 4바이트 정렬(5바이트 자료형 > 8바이트로 패딩, 11바이트 자료형 > 12바이트로 패딩, 즉 4의 배수로 패딩)되어 배치된다.

한마디로, 32비트 환경에서 가변인자로 들어온 값들은 언제나 값 그 자체들이 패딩되어 배치된다.

 

반면, 64비트 환경에서는 가변인자들은 무조건 8바이트 간격으로 패딩되어 배치되며, 8바이트를 초과하는 데이터의 경우 값 대신 그 데이터를 가리키는 주소가 배치되는 것으로 유추했다(위 블로그 글 참조).

즉, 8바이트 이하의 자료형의 경우 va_arg(ap, type)은 ap를 한 번 역참조하여 얻은 값과 같고, 초과하는 경우 ap를 두 번 역참조하여 얻은 값인 것이다.