strtok_r() 함수는 strtok() 함수와 매우 유사하지만, 결정적인 차이점이 하나 있습니다. 바로 함수 이름 끝에 붙은 _r이 의미하는 '재진입(re-entrant)' 기능입니다.
재진입 가능한(re-entrant) 함수란 실행 도중에 중단되었다가, 나중에 중단된 지점부터 실행을 안전하게 재개할 수 있는 함수를 말합니다.
이러한 특성 덕분에 재진입 함수는 스레드로부터 안전(thread-safe)합니다. 즉, 여러 스레드가 동시에 호출하거나 실행 중에 인터럽트가 발생해도 데이터가 손상되지 않고 안전하게 동작합니다.
strtok_r() 함수는 일반적인 strtok()에는 없는 추가 매개변수인 컨텍스트(context)를 가지고 있으며, 이를 통해 함수가 중단된 정확한 위치에서 실행을 이어갈 수 있습니다.
문법(Syntax)
strtok_r() 함수의 문법은 다음과 같습니다:
#include <string.h> char *strtok_r(char *string, const char *limiter, char **context);
각 매개변수의 역할은 다음과 같습니다:
- string: 토큰으로 분리할 대상 문자열 (첫 호출 시에만 전달)
- limiter: 문자열을 나눌 기준이 되는 구분자(delimiter) 집합
- context: 토큰화 진행 상태를 저장하는 포인터로, 후속 호출 시 위치를 기억하는 데 사용됩니다
예제(Example)
다음은 strtok_r() 함수를 사용하여 공백을 기준으로 문자열을 토큰으로 분리하는 C 프로그램입니다:
#include <stdio.h>
#include <string.h>
int main(){
char input_string[] = "Hello Tutorials Point";
char token_list[20][20];
char* context = NULL;
char* token = strtok_r(input_string, " ", &context);
int num_tokens = 0; // 토큰 리스트의 인덱스. 리스트에 순서대로 추가
while (token != NULL){
strcpy(token_list[num_tokens], token); // 토큰을 리스트에 복사
num_tokens++;
token = strtok_r(NULL, " ", &context);
}
// 토큰 리스트 출력
printf("Token List:\n");
for (int i=0; i < num_tokens; i++) {
printf("%s\n", token_list[i]);
}
return 0;
}
코드의 핵심 흐름을 살펴보면 다음과 같습니다:
- 첫 번째 호출에서는 분리할 문자열
input_string과 구분자" "(공백), 그리고 컨텍스트 변수의 주소를 전달합니다. - 이후 반복문 안에서는 첫 번째 인수로
NULL을 전달하여, 이전 호출의 중단 지점부터 계속해서 다음 토큰을 가져옵니다. - 더 이상 토큰이 없으면
NULL이 반환되며 반복문이 종료됩니다.
실행 결과(Output)
위 프로그램을 실행하면 다음과 같은 결과가 출력됩니다:
Token List: Hello Tutorials Point
이처럼 strtok_r() 함수는 멀티스레드 환경에서 여러 스레드가 동시에 서로 다른 문자열을 토큰화해야 할 때 특히 유용합니다. 내부 상태를 공유하는 strtok()와 달리, 각 호출마다 독립적인 컨텍스트를 사용하기 때문에 스레드 간 간섭 없이 안전하게 사용할 수 있습니다.