strtol(3)
๐ strtol(3) โ string to long int ๐
okay bestie, gather round, because today we're talking about strtol, strtoll, and strtoq โ the trio that turns your little text strings into actual numbers. it's giving โจ conversion era โจ and honestly? iconic. this whole page lives in the Library Functions Manual corner of the man pages, and yeah, it's the Standard C library (libc, -lc). no cap.
โจ NAME โจ
strtol, strtoll, strtoq โ string to long int ๐
๐ซถ LIBRARY ๐ซถ
Standard C library (libc, -lc)
๐ธ SYNOPSIS ๐ธ
#include <stdlib.h>
long strtol(const char *restrict nptr,
char **_Nullable restrict endptr, int base);
long long strtoll(const char *restrict nptr,
char **_Nullable restrict endptr, int base);
๐ฆ Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
strtoll():
_ISOC99_SOURCE
|| /* glibc <= 2.19: */ _SVID_SOURCE || _BSD_SOURCE
๐ DESCRIPTION ๐
so strtol() takes the first part of the string sitting in nptr and converts it into a long integer value, using whatever base you hand it. and that base? it's gotta be between 2 and 36 inclusive, OR the special value 0 if you want it to figure things out itself. main character energy fr fr.
the string is allowed to start with a totally arbitrary amount of white space (whatever isspace(3) says counts as white space), and then a single optional '+' or '-' sign. then:
- if
baseis zero or16, the string can also have a"0x"or"0X"prefix, and the number gets read in base 16 ๐ฅ - if
baseis zero or2, the string can have a"0b"or"0B"prefix, and the number gets read in base 2 ๐ - otherwise, a zero base is taken as
10(decimal) โ unless the next character is'0', in which case it's taken as8(octal). sneaky but true ๐
then the rest of the string gets converted to a long value "in the obvious manner", stopping at the very first character that isn't a valid digit in the base you picked. and yes bestie, in bases above 10, the letter 'A' (uppercase or lowercase, we don't discriminate) means 10, 'B' means 11, and on and on it goes, all the way up โ with 'Z' representing 35. the alphabet is literally the digits now ๐
now, if endptr isn't NULL and the base is supported, strtol() stores the address of that first invalid character into *endptr. if there were no digits at all?? then strtol() stores the original value of nptr in *endptr (and returns 0). and here's the cute little detail: if *nptr isn't '\0' but **endptr IS '\0' on return, that means the whole entire string was valid. slay ๐
strtoll() works exactly like strtol() but returns a long long integer value instead. tiny glow-up, same vibe โจ
๐ RETURN VALUE ๐
strtol() returns the result of the conversion... unless the value would underflow or overflow ๐ญ
- underflow? you get
LONG_MINback - overflow? you get
LONG_MAXback
and in BOTH of those cases, errno gets set to ERANGE. precisely the same thing holds for strtoll(), except with LLONG_MIN and LLONG_MAX instead of LONG_MIN and LONG_MAX. periodt.
๐ ERRORS ๐
listen. this function does not modify errno on success. obsessed, actually.
EINVAL(not in C99) โ thebaseyou gave contains an unsupported value ๐ERANGEโ the resulting value was out of range
also, the implementation may seterrnotoEINVALin the case where no conversion was performed (no digits seen, and0returned). so like, don't be shocked if you see it.
๐ ATTRIBUTES ๐
for an explanation of the terms used in this section, see attributes(7).
strtol(),strtoll(),strtoq()โ Thread safety:MT-Safe locale
(the original is a cute little table withInterface/Attribute/Valuecolumns, but you get the deets either way, bestie ๐)
๐ง VERSIONS ๐ง
according to POSIX.1, in locales that aren't "C" and "POSIX", these functions may accept other, implementation-defined numeric strings. iykyk.
BSD also has:
quad_t strtoq(const char *nptr, char **endptr, int base);
with a completely analogous definition, no cap. and depending on the wordsize of the current architecture, this may be equivalent to strtoll() or to strtol(). it's giving "who am i today" ๐ญ
โญ STANDARDS โญ
C23, POSIX.1-2024.
๐ธ HISTORY ๐ธ
strtol()โ POSIX.1-2001, C89, SVr4, 4.3BSD.strtoll()โ POSIX.1-2001, C99."0b","0B"โ C23. glibc 2.38. (Not in POSIX.) ๐
๐ CAVEATS ๐
๐ฅ Range checks
okay this is the important part so pay attention: since strtol() can legitimately return 0, LONG_MAX, or LONG_MIN (or LLONG_MAX / LLONG_MIN for strtoll()) on both success and failure, your calling program should set errno to 0 before the call, and then figure out if an error happened by checking whether errno == ERANGE after the call. like, actually do this. fr fr.
errno = 0;
n = strtol(s, &end, base);
if (end == s)
goto no_number;
if ((errno == ERANGE && n == _Minof(long)) || n < min)
goto too_low;
if ((errno == ERANGE && n == _Maxof(long)) || n > max)
goto too_high;
๐ฆ base
if the base needs to be tested, it should be tested in a call where the string is known to succeed. otherwise it's impossible to portably differentiate the errors. portability bestie, we love her ๐
errno = 0;
strtol("0", NULL, base);
if (errno == EINVAL)
goto unsupported_base;
๐ BUGS ๐
๐ White space
these functions silently accept leading white space. no warning, no drama, just vibes. to reject white space, call isspace(3) before strtol(). that's the whole trick ๐
๐ EXAMPLES ๐
the program down below demonstrates the use of strtol(). the first command-line argument specifies a string from which strtol() should parse a number. the second (optional) argument specifies the base to be used for the conversion. (and that second argument gets converted to numeric form using atoi(3) โ a function that performs no error checking and has a simpler interface than strtol(). living dangerously, honestly ๐ญ)
some examples of the results produced by this program:
$ ./a.out 123
strtol() returned 123
$ ./a.out ' 123'
strtol() returned 123
$ ./a.out 123abc
strtol() returned 123
Further characters after number: "abc"
$ ./a.out 123abc 55
strtol: Invalid argument
$ ./a.out ''
No digits were found
$ ./a.out 4000000000
strtol: Numerical result out of range
โจ Program source
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int base;
char *endptr, *str;
long val;
if (argc < 2) {
fprintf(stderr, "Usage: %s str [base]\n", argv[0]);
exit(EXIT_FAILURE);
}
str = argv[1];
base = (argc > 2) ? atoi(argv[2]) : 0;
errno = 0; /* To distinguish success/failure after call */
strtol("0", NULL, base);
if (errno == EINVAL) {
perror("strtol");
exit(EXIT_FAILURE);
}
errno = 0; /* To distinguish success/failure after call */
val = strtol(str, &endptr, base);
/* Check for various possible errors. */
if (errno == ERANGE) {
perror("strtol");
exit(EXIT_FAILURE);
}
if (endptr == str) {
fprintf(stderr, "No digits were found\n");
exit(EXIT_FAILURE);
}
/* If we got here, strtol() successfully parsed a number. */
printf("strtol() returned %ld\n", val);
if (*endptr != '\0') /* Not necessarily an error. */
printf("Further characters after number: \"%s\"\n", endptr);
exit(EXIT_SUCCESS);
}
๐ SEE ALSO ๐
atof(3), atoi(3), atol(3), strtod(3), strtoimax(3), strtoul(3)
and that's the whole page, bestie!! this fam was brought to you by the Linux man-pages 6.20, dated 2026-07-26 โ go forth and parse 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 1993, David Metcalfe <david@prism.demon.co.uk>
- Copyright 2006, 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