주요 개념
Printf 구현을 위한 전체적인 그림
- 가변인자를 처리해주기 위한 로직 작성
- 각 가변인자의 자료구조에 따라서 처리해주는 함수 작성
--> c(캐릭터), s(문자열), p(주소), d(정수), i(정수), u(자연수), x(16진수-소문자), X(16진수-대문자)
- 각 자료형에 따라서 처리된 값을 표준출력(STDOUT)으로 출력
- Printf의 자료형이 int형으로 반환값은 출력한 문자열의 전체적인 길이를 의미 -> 만약 int형의 범위를 벗어날경우, 아무것도 출력하지않고 -1값을 반환
가변인자
- 인자를 받을 때, 정해진 자료형 및 개수가 정해지지 않은 인자를 뜻함
- 개수 및 자료형이 정해지지 않은 인자
가변인자 처리 함수
va_start(va_list ap, last)
- 가변인자를 사용하기 위해서 초기화의 개념을 가지고 있는 함수
- 가변인자인 ap를 가장 처음으로 돌리고, last는 가변 인자 목록 전의 마지막 인자, 즉 호출 함수에서 타입을 알고 있는 마지막 인자의 이름
va_end(va_list ap)
- va_start를 통해서 가변인자를 사용한 후, 가변인자의 사용 종료를 선언하는 함수
va_copy(va_list dest, va_list src)
- 가변인자를 복사하기 위한 함수로, dest에 src의 인자를 복사해서 생성
va_arg(va_list ap, type)
-
va_start를 한 후, 직후에 사용하면 해당 시작지점의 가변인자를 뜻하고, va_arg가 한번 호출 된 후, 그 다음의 ap는 그 다음의 가변인자를 의미
-
type에는 각 가변인자에서 사용된 type를 명시해주면 되며, 일반적으로는 마지막에 사용된 가변인자의 type을 반환하게 됨
Printf 구현하기(플래그는 구현 X)
1. Printf의 프로토타입
int printf(const char *arr, ...)
-> 가변인자의 입력 전에 입력받은 배열이 있을경우, 그 배열이 arr을 의미
-> ... 이 부분이 가변인자를 사용한다는것을 의미
2.va_start함수 사용
va_list temp;
va_start(temp, arr);
-> 가변인자의 자료형인 va_list를 시작위치로 옮겨주고, 마지막에 명시되었던 arr을 명시해줌으로
-> 가변인자를 사용하겠다는 의미
3. %기준 파싱
-> 예시. 만일 printf("hello everyone, my number is %d"); 입력이 들어오게 될 경우
-> %이전의 값은 그대로 출력을 해주고 %뒤의 문자에 따라서 타입을 결정해서 처리
4. 자료구조 별 처리함수
-> c의 경우, 문자 그대로 출력을 해주고 1의 길이를 반환
-> s의 경우, 문자열을 그대로 출력해주고, 문자열의 길이만큼 반환
-> p의 경우, 주소값을 출력해주며, 주소값의 길이를 반환
-> d, i의 경우, 정수값을 출력해주며, 정수의 길이를 반환
-> u의 경우, 자연수값을 출력해주며, 자연수의 길이를 반환
-> x의 경우, 16진수(소문자)를 출력해주며, 16진수의 길이를 반환
-> X의 경우, 16진수(대문자)를 출력해주며, 16진수의 길이를 반환
4-1. c 처리 로직
- c = va_arg(temp, int)를 통해서 가변인자를 사용한 뒤, 다음 가변인자로 이동을 시켜줌
- write(1, &c, 1); 등 처리함수를 통해서 출력한 후 1의 값 반환
4-2. s 처리 로직
- *s = a_arg(temp, char *)를 통해서 가변인자를 사용한 뒤, 다음 가변인자로 이동
- write(1, s, strlen(s)); 등 처리함수를 통해 출력한 후, strlen(s)를 반환
4-3. p 처리 로직
- p의 경우 0x가 출력이 되기 때문에 먼저 0x를 출력을 시킨 후, 16진수를 출력
- p = va_arg(temp, void *)를 통해서 가변인자 사용
- 받은 값을 각 자릿수별로 16진수로 변환한 뒤 출력한 후, 16진수의 길이 + 2를 반환
4-4. d,i 처리 로직
- d = va_arg(temp, int)를 통해 가변인자 사용
- p와 비슷하게 각 자릿수 별로 10진수값 출력한 후, 정수값의 자릿수 반환
4-5. u 처리 로직
- u = va_arg(temp, unsigned int)를 통해 가변인자 사용
- d,i와 비슷하게 처리를 하나, 자연수이므로 부호를 신경쓰지 않음
4-6. x, X 처리로직
- x = va_arg(temp, void *)를 통해 가변인자 사용
- x는 소문자, X는 대문자로 16진수를 사용하며 나머지는 p와 비슷하게 처리
길이 합산 및 반환
- 반환된 전체길이를 변수에 담아두고 이를 return 해주면 됨