#include <unistd.h>
#include <limits.h> // For INT_MIN
// 숫자를 문자열로 변환하고 출력하는 보조 함수
void func(char *buf, int *i, int *negative, int nb)
{
// 음수 처리
if (nb < 0) {
*negative = 1; // 음수 플래그를 1로 설정
nb = -nb; // 숫자를 양수로 변환 (음수 부호를 없앰)
}
// 숫자가 0인 경우
if (nb == 0) {
buf[(*i)++] = '0'; // 0을 문자열로 변환하여 버퍼에 저장
} else {
// 숫자를 문자열로 변환 (역순으로 저장)
while (nb > 0) {
buf[(*i)++] = (nb % 10) + '0'; // 숫자의 마지막 자릿수를 문자로 변환
nb /= 10; // 숫자의 마지막 자릿수를 제거
}
}
// 음수 기호 추가
if (*negative) {
buf[(*i)++] = '-'; // 음수였던 경우 '-' 기호를 추가
}
// 문자열을 역순으로 출력
while (*i > 0) {
write(1, &buf[--(*i)], 1); // 버퍼에서 문자 하나를 역순으로 출력
}
}
// 정수를 출력하는 함수
void ft_putnbr(int nb)
{
char buf[12]; // 최대 11자리 숫자 + '-' 기호 + null terminator
int i = 0; // 버퍼의 현재 인덱스
int negative = 0; // 음수 여부를 표시하는 플래그
// INT_MIN을 특별히 처리
if (nb == INT_MIN) {
write(1, "-2147483648", 11); // INT_MIN의 경우 고정 문자열을 직접 출력
return; // 함수 종료
}
// 숫자를 문자열로 변환하고 출력
func(buf, &i, &negative, nb);
// 왜 주소를 사용하는가 ?
// 주소를 사용하면 함수 호출 시 변수의 주소를 넘겨 메모리 복사 비용을 줄이는 것에 유용해 값의 전달이 가능하다.
}
// 테스트 함수
int main()
{
ft_putnbr(12345); // 출력: 12345
write(1, "\n", 1);
ft_putnbr(-6789); // 출력: -6789
write(1, "\n", 1);
ft_putnbr(0); // 출력: 0
write(1, "\n", 1);
ft_putnbr(2147483647); // 출력: 2147483647
write(1, "\n", 1);
ft_putnbr(INT_MIN); // 출력: -2147483648
write(1, "\n", 1);
return 0;
}
먼저 write 함수를 사용하는 이유에 대해서 알아보자. write는 시스템 콜로, 버퍼를 사용하지 않고 직접 파일 디스크립터에 데이터를 출력한다. printf와 같은 표준 라이브러리 함수는 내부적으로 버퍼링을 하며, 이 과정에서 메모리 할당과 처리가 복잡해질 수 있다. write를 사용하면 이러한 복잡성을 피할 수 있다. 이와 같은 write로 printf를 구현 해 보자.
기본 기능:
ft_putnbr 함수는 정수를 문자열로 변환하고, write 시스템 콜을 사용하여 이를 출력한다. 이 함수는 음수, 양수, 제로, 그리고 INT_MIN과 같은 특별한 경우를 처리할 수 있다.
함수 동작 과정:
INT_MIN의 경우, 직접 문자열을 출력한다. 이는 INT_MIN의 절대값이 int 범위를 초과하기 때문에 특별히 처리해야 하는 경우입이다.write 시스템 콜을 사용하여 직접 데이터를 출력한다.printf의 print 구현 비교:
printf:ft_putnbr: