atoi?

#include <string.h>

    int atoi(const char *nptr);

Linux manpage description

: The atoi() function converts the initial portion of the string pointed to by nptr to int. The behavior is the same as strtol(nptr, NULL, 10); except that atoi() does not detect errors.

해석 및 부연설명

: 포인터 nptr이 가리키는 문자열을 int로 변환하여 반환한다.

ex)

char	str[] = "-1535abcd";
printf("%d\n", atoi(str));

코드 실행 결과

-1535

’-‘부호가 적용되고, int로 표현할 수 있는 1535까지만 변환되어 반환되었다.

의문점 및 생각해볼점

  1. 정확한 작동방식
  2. int 범위를 넘어간다면

atoi는 어떻게 작동하는가

atoi 함수에는 여러가지 고려할 점이 있다.

  1. 처리하는 문자열의 범위 문자열을 앞에서부터 읽으면서 부호(+-)와 whitespace(space와 ascii기준 9~13)을 건너 띈 후 나오는 숫자부터 처리를 시작하며 숫자가 아닌 문자가 나오는 순간 끊는다.
  2. 부호 및 whitespace 처리 +나 -가 한번 나올 때 이를 반영하고, 또다시 부호가 등장한다면 이는 그냥 숫자가 아닌 여타 문자로 취급하여 끊어버린다. 이 때 순서는 무조건 whitespace > 부호 > 숫자여야 하며 부호 뒤에 whitespace가 온다면 이 또한 올바르지 않은 케이스가 되어 끊긴다.
  3. 정상적인 숫자가 들어오지 않았을 경우 변환될 숫자가 없이 문자열 읽기가 끊긴다면 0이 반환된다.

오버플로우/언더플로우시

int형 범위 2147483647을 넘어가면 오버플로우가 발생되어 엉뚱한 값이 나온다.
반대로 -2147483648보다 작으면 언더플로우가 발생해 엉뚱한 값이 나온다.
결론적으로 atoi 함수에서는 오버/언더플로우시에 따로 처리하는 기능이 없다.

단, long long형 범위를 넘어갈 시에는 조금 처리가 달라지는데 이는 atoi 함수 내부적으로 strtol 함수를 거친 값을 가지고 처리하기 때문이라고 한다.
즉, strtol 함수에서는 long long형 범위 이외의 값이 들어올 경우 오버플로우가 되면 최댓값인 9,223,372,036,854,775,807을, 언더플로우가 되면 최솟값인 -9,223,372,036,854,775,808를 고정적으로 반환하며 이 값들을 atoi에서 처리할 경우 또 오버플로우와 언더플로우가 발생해 각각 -1과 0이 반환된다.


ft_atoi 구현

#include <limits.h>

int	ft_atoi(const char	*str)
{
	unsigned long long	result;
	int					flag;

	result = 0;
	flag = 1;
	while ((*str >= 9 && *str <= 13) || *str == ' ')
		str++;
	if (*str == '-' || *str == '+')
	{
		if (*str == '-')
			flag = -1;
		str++;
	}
	while (*str)
	{
		if (*str >= '0' && *str <= '9')
			result = result * 10 + *str - '0';
		else
			break ;
		str++;
	}
	if (result > LONG_MAX)
		return (-1 + (flag < 0));
	return (flag * (int)result);
}

원본 atoi 함수와 같은 결과값이 나오도록, 읽어들인 값이 long long형의 범위를 넘어갔을 때는 limits.h헤더에서 long long형의 최대값과 같은 LONG_MAX가 고정적으로 적용되도록 처리하였다.