ft_strlen

ft_strlen

“ft_strlen에 대하여”

strlen, strnlen – find length of string

ft_strlen & 복합 연산자

<목차>

1. MY CODES

2. 이야깃거리

(1) MY CODES

#include "libft.h"

size_t	ft_strlen(const char *s)
{
	size_t	cnt;

	cnt = 0;
	while (*(s++))
		cnt++;
	return (cnt);
}
  • 매개변수로 들어온 문자열 s의 길이를 구해서 반환한다.

(2) 이야깃거리

1. NULL GUARD(예외 처리)

  • ft_strlen에 널 가드를 하느냐 마느냐가 또 뜨거운 감자다. 사실 하는지 마는지는 본인 마음이라고 생각한다만, 이때는 원본 strlen()을 참조하면 좋을 것 같다. 아래를 보자.
#include <stdio.h>
#include <string.h>

int main()
{
	size_t len2 = strlen(NULL);
	return 0;
}
  • 이 코드의 output은 어떨까?
❯ ./a.out
zsh: segmentation fault  ./a.out
  • 세그멘테이션 폴트가 발생한다. 즉 원본 strlen의 경우 NULL을 입력받으면 세그멘테이션 폴트를 발생시킨다. 이렇게 의도적으로 세그멘테이션 폴트를 발생시키는 것은 디버깅할 때 도움이 된다. 캐릭터 포인터 NULL을 가리키고 있다는 것은 초기화 작업이 생략되었다는 것이고 이는 추후에 문제를 일으킬 가능성이 있는데, 이것을 미리 파악할 수 있기 때문이다. 널 가드가 되어있어서 strlen을 빠져나갔다면 어딘가 다른 중요한 곳에서 문제를 발생시킬수도 있을 것이다.

  • 널 가드라는 표현… 42 Seoul에서만 쓰이는 표현으로 알려져 있다. 42 서울의 진한 향기를 느낄 수 있는 문학적(?) 표현이라고 볼 수도 있지 않을까?

(근데 libft를 전반적으로 예외 처리를 하지 않고 저장해두게 되면, 나중에 libft를 사용하게 되는 다른 과제들에서 libft를 수정해야 하는 일이 자주 생긴다(펑펑 터진다). 경험상 strlen 뿐만 아니라 많은 함수들이 그렇다. 나중에 과제에 가져다 쓸 libft는 예외 처리를 좀 해두거나 디버깅을 할 때 이 부분에 대해 항상 생각해야 한다.)

2. 복합 연산자

	while (*s++)
		cnt++;
  • 보기만 해도 머리가 아찔한 연산자 표현, 코드 길이를 줄이려는 처절한 몸부림이 느껴지는가?
	while (*s)
	{ // 1
		cnt++;
		s++; // 2
	} // 3
  • 복합 연산을 함으로써 3줄을 아낄 수가 있다. 25줄 안에 코드를 완성시켜야하는 환경에서는 이런 복합 연산에 목을 맬 수 밖에 없게 된다. 그러기 위해서는 연산자 계산 우선순위에 대해 신경 써야할 것이다. *(s++)의 경우 어떤 순서로 계산될까?
  1. 먼저 *s가 수행된다. 포인터 s가 현재 가리키고 있는 위치의 값을 가져온다.
  2. 이후 s++가 수행된다. 이는 포인터 s를 다음 위치로 이동시키는 연산자이다.
  • 즉 위 코드는 *s를 수행하여 while문의 조건에 맞는지 확인한 후, 조건에 부합한다면 s++을 통해 포인터를 다음 위치로 밀어두고 스코프 안으로 들어간다. cnt++를 수행한 이후로는 *s이 while문 조건에 맞지 않을 때까지 반복한다.

(3) ++s++

  • 제목에 박아놓은 ++s++, 이런 복합 연산이 가능할까? ++s++는 불가능한 복합 연산이다. 이는 오류를 발생시킨다. 그런데 (++s)++는 오류를 일으키지 않는다. 왜 그런 것일까?

  • 이 부분에 대해서는 지금 당장 이야기하지 않아도 될 것 같기 때문에 다른 글에서 다루고자 한다. 이유를 알아보고 싶다면 lvalue와 rvalue에 대해 공부하면 된다.