strtok_r(3)
π strtok_r(3) β string tokenize reentrant π
okay bestie, buckle up, we're talking about strtok_r from the Library Functions Manual β¨ it's the reentrant, no-drama, thread-safe glow-up of strtok, and honestly? she ate. π
It lives in the Standard C library, which is libc, which is -lc. iykyk π¦
β¨ SYNOPSIS β¨
#include <string.h>
char *strtok_r(char *_Nullable restrict str, const char *restrict delim,
char **restrict saveptr);
π§ Feature Test Macro Requirements for glibc π§
(wanna know what feature test macros even are? go read feature_test_macros(7), bestie π)
strtok_r():_POSIX_C_SOURCE|| /* glibc <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE
so like, yeah, if you're on old glibc you need one of those older macros too. vintage behavior, kinda iconic honestly πΈ
π DESCRIPTION π
So strtok_r() is literally just a reentrant version of strtok(3). that's the whole vibe. reentrant means she doesn't keep her state in some hidden global, she keeps it in a place you hand her, so multiple people can use her at once without chaos. main character energy but polite about it π
The saveptr argument is a pointer to a char * variable. strtok_r() uses it internally to keep track of context between calls that are parsing the same string. think of it as her little diary π
On the first call to strtok_r(), str should point to the string you wanna parse, and the value of *saveptr is ignored β but fr fr, see VERSIONS below, there's a lil caveat there π
On subsequent calls, str should be NULL, and saveptr (plus the buffer it points to) should be unchanged since the previous call. don't touch the diary. the diary stays where it is. π€
And here's the slay part: different strings can be parsed concurrently using sequences of calls to strtok_r() that specify different saveptr arguments. nested loops? multiple parses at once? she said "bet." π₯
π« RETURN VALUE π«
strtok_r() returns a pointer to the next token, or NULL if there are no more tokens. that's it, that's the whole return value. no hidden extra errno nonsense, just token or nothing. periodt. π
π ATTRIBUTES π
for an explanation of the terms used in this here section, go check attributes(7) β she explains it all, bestie π«Ά
- Interface:
strtok_r() - Attribute: Thread safety
- Value:
MT-Safe
yup. MT-Safe. she's safe to use across threads and that is the personality trait, no cap β
π¦ VERSIONS π¦
okay so on some implementations, *saveptr is required to be NULL on the first call to strtok_r() that's being used to parse str. this is why I told you to peep down here. if you're writing portable code, just set it to NULL on the first call and you'll never get caught out π
πΈ STANDARDS πΈ
POSIX.1-2008.
β¨ HISTORY β¨
POSIX.1-2001.
she's been around. a legend. π
π EXAMPLES π
the program down below uses nested loops that employ strtok_r() to break a string into a two-level hierarchy of tokens. so like tokens made of subtokens. very inception, very cute π
- the first command-line argument specifies the string to be parsed
- the second argument specifies the delimiter byte(s) used to separate that string into "major" tokens
- the third argument specifies the delimiter byte(s) used to separate the "major" tokens into subtokens
an example of the output produced by this program is the following:
$ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
1: a/bbb///cc
--> a
--> bbb
--> cc
2: xxx
--> xxx
3: yyy
--> yyy
look at her go π so clean. the major delimiters split on :; and then each piece gets split again on /. triple slashes? handled. vibes? immaculate β¨
π Program source π
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
char *str1, *str2, *token, *subtoken;
char *saveptr1, *saveptr2;
int j;
if (argc != 4) {
fprintf(stderr, "Usage: %s string delim subdelim\n",
argv[0]);
exit(EXIT_FAILURE);
}
for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
token = strtok_r(str1, argv[2], &saveptr1);
if (token == NULL)
break;
printf("%d: %s\n", j, token);
for (str2 = token; ; str2 = NULL) {
subtoken = strtok_r(str2, argv[3], &saveptr2);
if (subtoken == NULL)
break;
printf("\t --> %s\n", subtoken);
}
}
exit(EXIT_SUCCESS);
}
see how the outer loop passes argv[1] on the first pass and then NULL after? and the inner loop does the same thing with token and NULL? that's the entire trick, bestie. two separate saveptrs, two separate diaries, zero interference. she's literally built for this π
π SEE ALSO π
lowkey reminder: the originalstrtok(3)is not thread safe, which is the whole reasonstrtok_rexists. so if you're in a multithreaded situation, use the_rone. no cap. π
that's the whole page, girlies β this was strtok_r(3) from Linux man-pages 6.20, dated 2026-02-25, and yes the title is still strtok_r(3) in case you got lost in my paragraphs π₯° mwah, go tokenize something responsibly πβ¨ππ¦πΈπ
π«Ά
π¦ where this page comes from
- arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- π the page's license: Linux-man-pages-copyleft
- Copyright 2005-2013, Michael Kerrisk <mtk.manpages@gmail.com>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms