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 base is zero or 16, the string can also have a "0x" or "0X" prefix, and the number gets read in base 16 ๐Ÿ”ฅ
  • if base is zero or 2, 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 as 8 (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_MIN back
  • overflow? you get LONG_MAX back

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) โ€” the base you gave contains an unsupported value ๐Ÿ™ˆ
  • ERANGE โ€” the resulting value was out of range
also, the implementation may set errno to EINVAL in the case where no conversion was performed (no digits seen, and 0 returned). 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 with Interface / Attribute / Value columns, 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
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms