ft_atoi
구현을 위해 stdlib.h
헤더의 atoi()
함수를 사용하여 다음과 같이 여러가지 값으로 테스트 해보았다.
printf("return(MIN) : %d\n", atoi("-2147483648")); // -2147483648
printf("return(MAX) : %d\n", atoi("2147483647")); // 2147483647
printf("return(MIN-1) : %d\n", INT_MAX); // 2147483647
printf("return(MIN-1) : %d\n", atoi("-2147483649")); // 2147483647
printf("return(MAX+1) : %d\n", INT_MIN); // -2147483648
printf("return(MAX+1) : %d\n", atoi("2147483648")); // -2147483648
printf("return(123aa) : %d\n", atoi("123aa")); // 123
printf("return(123 123) : %d\n", atoi("123 123")); // 123
printf("return(--123) : %d\n", atoi("--123")); // 0
printf("return(-+-123) : %d\n", atoi("-+-123")); // 0
printf("return(++123) : %d\n", atoi("++123")); // 0
printf("return(+-123) : %d\n", atoi("+-123")); // 0
printf("return(-+123) : %d\n", atoi("-+123")); // 0
테스트 후 예외 처리 해야하는 부분을 체크하였다.
언더플로우와 오버플로우에 대한 처리를 어떻게 할까
언더플로우 오버플로우때의 규칙을 찾기위해 다음과 같은 규칙을 찾았다
엄청난 삽질 및 뻘짓
atoi(x)
라고 했을때,
x > INT_MAX 인 경우
x / INT_MAX 가 홀수인 경우 리턴값
(INT_MAX - (x / INT_MAX) - 1) + (x % INT_MAX)
x / INT_MAX 가 짝수인 경우 리턴값
((x / INT_MAX) * -1) + (x % INT_MAX)
x < INT_MIN 인 경우
x / INT_MIN 가 홀수이며, 나머지가 없는 경우 리턴값
INT_MIN
x / INT_MIN 가 홀수이며, 나머지가 있는 경우 리턴값
MAX + (x % min + 1)
x / INT_MIN 가 짝수인 경우 리턴값
x % min
규칙을 다 찾은 후 기쁨도 잠시, 세운 식들을 살펴보면서 무언가 잘못돌아가고 있는것이 느껴지기 시작했다.
'뭔가.. 복잡한데 진짜 이렇게까지 예외처리를 해야하는 걸까..'라는 생각이 들었다. 그제서야 서둘러 slack에 검색하여 다른 사람들이 올린 질문과 답변을 살펴보았다.
친절한 카뎃 quartz
와 mhouppin
의 답변에 의해 해답을 찾을 수있었다.
atoi()
함수는 libc에 의해 stdtol()
를 내부로 돌려서 결과값을 리턴하는 방식을 가졌다.atoi()
의 리턴 타입은 int, strtol()
의 리턴 타입은 long 이다.atoi()
에서 나오는 언더플로우/오버플로우의 리턴값은 strtol()
에서 나온 결과값을 처리하는 과정에서 나오는 ERANGE
오류이다.strtol()
함수에 오버플로우 값이 들어오면 LONG_MAX, 언더플로우 값이 들어오면 LONG_MIN을 리턴한다.atoi()
함수에 LONG 오버플로우 값이 들어오면 -1, 언더플로우 값이 들어오면 0을 리턴한다.printf("return(MAX) : %ld\n", LONG_MAX); // 9223372036854775807
printf("return(MIN) : %ld\n", LONG_MIN); // -9223372036854775808
printf("return(-6442) : %d\n", atoi("-6442")); // -6442
printf("return(-6442) : %ld\n", strtol("-6442",NULL,10)); // -6442
printf("return(MAX) : %ld\n", strtol("9223372036854775807",NULL,10)); // 9223372036854775807
printf("return(MAX+1) : %ld\n", strtol("9223372036854775808",NULL,10)); // 9223372036854775807
printf("return(MIN) : %ld\n", strtol("-9223372036854775808",NULL,10)); // -9223372036854775808
printf("return(MIN-1) : %ld\n", strtol("-9223372036854775809",NULL,10)); // -9223372036854775808
printf("return(LONGMAX) : %d\n", atoi("9223372036854775807")); // -1
printf("return(LONGMIN) : %d\n", atoi("-9223372036854775809")); // 0
결론 : libft에서는 굳이 이러한 오버플로우/언더플로우 처리값까진 신경쓰지 않으므로 무시해도 된다.😂