C Standard Library errno.h

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
<errno.h>

What You’ll Learn

The <errno.h> header defines errno, a shared error indicator that many C library functions set when something goes wrong. Combined with return-value checks and helpers like perror and strerror, it lets your program report failures clearly instead of crashing silently.

01

errno

Error code.

02

EDOM

Bad input.

03

ERANGE

Overflow.

04

perror

Print error.

05

Reset

errno = 0.

06

Return

Check first.

Definition and Usage

errno is a macro that expands to a modifiable int lvalue. When a library function fails, it often stores a positive error code in errno so your program can tell why it failed. At program startup, errno is zero.

Crucially, library functions do not clear errno on success. A leftover value from an earlier error can mislead you if you read errno without checking the function’s return value or without resetting errno before the call.

💡
Beginner Tip

The safe pattern is: check the return value first (e.g. if (fp == NULL)), then read errno. For functions like strtol, set errno = 0 immediately before the call.

📝 Syntax

Include the header:

C
#include <errno.h>

The errno macro

Portable code uses errno directly after including the header. You do not need to write extern int errno; yourself.

C
errno = 0;              /* reset before a call when needed */
if (some_call() fails) {
    if (errno != 0) {   /* inspect error code */
        /* handle error */
    }
}

Common error macros (errno.h)

  • EDOM — domain error (invalid argument to a math function, e.g. sqrt(-1)).
  • ERANGE — range error (result too large or too small to represent).
  • EINVAL — invalid argument (common on POSIX systems).
  • EINTR — interrupted system call (POSIX).
  • ENOMEM — not enough memory (POSIX).

Additional codes like ENOENT (“No such file or directory”) come from the host system and are used by functions such as fopen.

Related helpers (other headers)

  • perror(const char *s) — prints s plus error message to stderr (<stdio.h>).
  • strerror(int errnum) — returns a string for error code errnum (<string.h>).

Headers and linking

  • #include <errno.h> for errno, EDOM, ERANGE.
  • #include <stdio.h> for perror; #include <string.h> for strerror.
  • Math examples: gcc program.c -std=c11 -lm -o program

⚡ Quick Reference

SymbolMeaningTypical use
errnoLast error codeRead after failed call
EDOMDomain errorsqrt(-1), invalid math input
ERANGERange errorOverflow in strtol, huge exp
perror("msg")Print to stderrperror("fopen")
strerror(errno)Error stringprintf("%s", strerror(errno))
Reset
errno = 0;

Before strtol

File I/O
if (fp == NULL)

Then read errno

perror
perror("open");

Quick debug

strerror
strerror(errno)

Custom format

Examples Gallery

Compile with gcc file.c -std=c11 -o out. Add -lm for math examples. Always check return values; use errno to learn why a documented failure happened.

📚 Getting Started

Report file and math errors with errno, perror, and strerror.

Example 1 — Open a Missing File with strerror

Classic pattern from the reference: fopen returns NULL on failure and sets errno.

C
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(void) {
    FILE *file = fopen("nonexistent.txt", "r");

    if (file == NULL) {
        printf("Error opening file: %s (errno=%d)\n",
               strerror(errno), errno);
    } else {
        fclose(file);
    }

    return 0;
}

How It Works

fopen fails because the file does not exist. We check file == NULL first, then use strerror(errno) for a readable message. On Linux, errno 2 is typically ENOENT.

Example 2 — Math Domain Error with perror

sqrt(-1) is invalid; errno is set to EDOM. Link with -lm.

C
#include <errno.h>
#include <math.h>
#include <stdio.h>

int main(void) {
    errno = 0;
    double result = sqrt(-1.0);

    printf("sqrt(-1) = %g\n", result);

    if (errno == EDOM) {
        perror("sqrt domain error");
    }

    return 0;
}

How It Works

We reset errno before sqrt so we know the error came from this call. The function still returns NaN; checking errno == EDOM confirms a domain error. perror prints to stderr with a colon and the system message.

📈 Practical Patterns

Parsing, comparing error helpers, and the reset-before-call idiom.

Example 3 — Detect Overflow with strtol and ERANGE

strtol returns a value even on failure—you must reset errno and check it.

C
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    const char *big = "999999999999999999999";
    char *end = NULL;
    long value;

    errno = 0;
    value = strtol(big, &end, 10);

    if (errno == ERANGE) {
        printf("Overflow: value out of long range\n");
    } else if (end == big) {
        printf("No digits parsed\n");
    } else {
        printf("Parsed: %ld\n", value);
    }

    return 0;
}

How It Works

Without errno = 0 first, a stale errno could falsely suggest overflow. ERANGE means the numeric result cannot fit in a long. Also check end to detect invalid input.

Example 4 — perror vs strerror Side by Side

Two ways to show the same file-not-found error.

C
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(void) {
  if (fopen("missing.dat", "r") == NULL) {
    perror("perror says");                    /* to stderr */
    printf("strerror says: %s\n", strerror(errno));  /* to stdout */
  }
  return 0;
}

How It Works

perror adds your prefix and a newline on stderr—ideal for quick debugging. strerror gives you a string to format in logs or GUI messages. Both read the current errno.

Example 5 — Why You Must Reset errno

Demonstrates how a leftover errno causes a false alarm if you skip the reset.

C
#include <errno.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    /* Simulate an earlier error */
    errno = EDOM;

    /* Successful call — does NOT clear errno */
    char msg[] = "hello";
    size_t len = strlen(msg);

    printf("strlen = %zu\n", len);

    if (errno != 0) {
        printf("False alarm: errno is still %d (%s)\n",
               errno, strerror(errno));
    }

    /* Correct approach for the next operation */
    errno = 0;
    len = strlen(msg);
    if (errno != 0) {
        printf("strlen failed?\n");
    } else {
        printf("After reset: errno is 0 (correct)\n");
    }

    return 0;
}

How It Works

strlen never touches errno, but the old EDOM value remains. This is why you check return values for functions that signal failure that way, and reset errno only when the function you are about to call documents errno usage.

🚀 Common Use Cases

  • File I/O — report why fopen, read, or fwrite failed.
  • String-to-number parsing — detect overflow and invalid input with strtol/strtod.
  • Math libraries — catch EDOM and ERANGE from sqrt, log, exp.
  • CLI tools — print friendly errors with perror when system calls fail.
  • Logging — store strerror(errno) in log files with timestamps.
  • Defensive libraries — document which error codes your wrapper sets for callers.

🧠 How errno.h Works

1

Call library function

Optionally set errno = 0 first if the function uses errno on failure.

Invoke
2

Check return value

NULL, -1, EOF, or NaN—each function documents its failure signal.

Validate
3

Read errno

If failure, errno holds a positive code (e.g. EDOM, ENOENT).

Inspect
=

Report or recover

Use perror, strerror, or branch on specific codes.

📝 Notes

  • errno is a macro, not a normal global variable you declare yourself.
  • Since C11, errno is thread-local—each thread has its own value.
  • Successful calls may leave errno unchanged; never assume it is zero after success.
  • Only read errno immediately after a failed call—other calls may overwrite it.
  • strerror returns a pointer to a static buffer; it may be overwritten by the next strerror call.
  • Math functions may also set the floating-point exception flags; errno is one part of error reporting.

⚡ Optimization

Reading and setting errno is negligible overhead. In release builds, focus on correct error paths rather than avoiding errno. For hot paths, still check return values; skip string formatting (perror/strerror) unless you actually report the error.

Conclusion

<errno.h> is the standard way C programs learn why a library call failed. Combine return-value checks with errno, reset before calls when required, and use perror or strerror for human-readable messages.

For development-time bugs, use <assert.h>; for real runtime failures users might trigger, use errno and proper error handling.

💡 Best Practices

✅ Do

  • Check return values before reading errno
  • Set errno = 0 before strtol, strtod, etc.
  • Use perror or strerror for messages
  • Read errno immediately after a failed call
  • Include <errno.h> for portable access to errno

❌ Don’t

  • Assume errno == 0 means the last call succeeded
  • Write extern int errno; instead of including the header
  • Ignore return values and rely only on errno
  • Compare errno after unrelated function calls
  • Use assert for expected user errors (files missing, bad input)

Key Takeaways

Knowledge Unlocked

Five things to remember about errno.h

Error handling in C, explained simply.

5
Core concepts
📚 02

Return

Check first.

Pattern
📈 03

Reset

errno = 0.

Safety
📄 04

EDOM

Bad input.

Math
🌐 05

perror

Print msg.

Report

❓ Frequently Asked Questions

errno.h declares the errno macro—a modifiable int lvalue that library functions set when they fail. It also defines error code macros like EDOM and ERANGE. Include it with #include <errno.h> whenever you inspect or reset errno.
errno is a macro that expands to an lvalue (often thread-local since C11). You do not declare extern int errno yourself in portable code; just #include <errno.h> and use errno directly.
Set errno = 0 immediately before a call when you need to know whether that specific call failed—especially for functions like strtol() that return a value on both success and failure. Many functions only set errno on error and leave it unchanged on success.
perror(msg) prints your message plus a system error string for the current errno to stderr. strerror(errno) returns a pointer to a human-readable string you can pass to printf. perror needs <stdio.h>; strerror needs <string.h>.
No. Always check the function's return value first (NULL, -1, EOF, etc.). Only some functions document that they set errno on failure—fopen, strtol, and many math functions do; others may not touch errno at all.
EDOM means a domain error (invalid input to a math function, e.g. sqrt(-1)). ERANGE means a range error (result too large, e.g. overflow in strtod). Both are macros defined in errno.h with positive integer values.
Did you know?

Before standardized errno, Unix programs each invented their own error reporting. Today errno is specified in C and is thread-local in modern implementations—but the habit of checking return values first is still essential, because not every failed function sets errno, and successful calls never guarantee it is zero.

Explore C Standard Library Headers

Continue with float.h or browse the library index.

Standard Library Index →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful