C String strerror() Function

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

What You’ll Learn

The strerror() function turns a numeric error code into a readable English message. After a failed call like fopen, you read errno and pass it to strerror to explain what went wrong to users or logs.

01

errno

Error number.

02

Text

Human message.

03

char*

Return ptr.

04

Read early

Save errno.

05

string.h

Standard C.

06

vs perror

Print stderr.

Definition and Usage

When a C library function fails, it often sets the global variable errno to a positive integer code. strerror(errnum) maps that integer to a short descriptive string supplied by the implementation.

The returned pointer usually points to static memory inside the C library. Treat it as read-only and copy the text with strdup or snprintf if you need to keep it across later library calls.

💡
Beginner Tip

Save errno right away: int err = errno; then strerror(err). Other functions (including printf in some cases) can overwrite errno if you wait too long.

📝 Syntax

Standard C declaration:

C
char *strerror(int errnum);

Headers

  • #include <string.h> — for strerror
  • #include <errno.h> — for errno and codes like ENOENT

Parameter

  • errnum — error number (typically the value of errno).

Return Value

  • Pointer to an implementation-defined error message string.
  • For unknown codes, message may be "Unknown error" or similar.

⚡ Quick Reference

ConstantTypical meaningExample message
ENOENTFile not foundNo such file or directory
EACCESPermission deniedPermission denied
ENOMEMOut of memoryCannot allocate memory
EINVALInvalid argumentInvalid argument
usagestrerror(errno) after failure
Message
strerror(errno)

After fail

Save first
err = errno;

Safe pattern

Quick print
perror("open");

To stderr

Log format
fprintf(stderr, "%s\n", ...)

Custom text

Examples Gallery

Compile with gcc strerror.c -std=c11 -o strerror. Error text may vary slightly by operating system, but common codes like ENOENT are portable.

📚 Getting Started

Report why opening a missing file failed.

Example 1 — File Open Error

Use strerror after fopen returns NULL.

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

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

    if (file == NULL) {
        int err = errno;
        printf("Error opening file: %s\n", strerror(err));
        return 1;
    }

    fclose(file);
    return 0;
}

How It Works

fopen sets errno to ENOENT when the path does not exist. strerror converts that code to readable text for your user or log file.

Example 2 — Save errno Before Other Calls

Capture the error code before any function that might change errno.

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

int main(void) {
    FILE *f = fopen("missing.dat", "rb");
    if (f == NULL) {
        int saved = errno;

        /* Other work here will not lose the original errno */
        printf("Failed (code %d): %s\n", saved, strerror(saved));
        return 1;
    }

    fclose(f);
    return 0;
}

How It Works

Storing errno in saved preserves the original failure reason even if later I/O or string functions update the global errno variable.

📈 Practical Patterns

Compare with perror, use known codes, and build a log helper.

Example 3 — strerror() vs perror()

Two ways to report the same file error.

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

int main(void) {
    FILE *f = fopen("nope.txt", "r");
    if (f == NULL) {
        int err = errno;

        fprintf(stderr, "Custom: %s\n", strerror(err));
        errno = err;
        perror("perror prefix");
    }

    return f == NULL ? 1 : 0;
}

How It Works

strerror gives you a string to format yourself. perror prints your prefix plus the current errno message to stderr in one call.

Example 4 — Pass a Known Error Code

You can call strerror with constants directly for demos or tests.

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

int main(void) {
    printf("ENOENT: %s\n", strerror(ENOENT));
    printf("EINVAL: %s\n", strerror(EINVAL));

    return 0;
}

How It Works

Standard macros like ENOENT expand to integer codes. strerror looks up the locale-dependent message table entry for each.

Example 5 — Small Error Logging Helper

Wrap strerror in a function for consistent log lines.

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

void log_errno(const char *action) {
    int err = errno;
    fprintf(stderr, "[ERROR] %s failed: %s (code %d)\n",
            action, strerror(err), err);
}

int main(void) {
    if (fopen("ghost.txt", "r") == NULL) {
        log_errno("fopen");
        return 1;
    }
    return 0;
}

How It Works

A helper reads errno immediately and formats action, message, and numeric code—useful across a project for uniform error reporting.

🚀 Common Use Cases

  • File I/O failures — explain missing paths or permission errors.
  • Network/socket code — combine with platform APIs that set errno.
  • Debugging — print numeric code plus readable text in logs.
  • User interfaces — show friendly messages instead of raw integers.
  • Unit tests — assert expected error codes and look up messages.

🧠 How strerror() Works

1

Library call fails

Function sets errno to a positive code.

errno
2

You pass errnum

Usually the saved errno value.

Input
3

Lookup message table

Runtime maps code to localized/system text.

Lookup
=

char* message

Read-only text—print or copy if you need to keep it.

📝 Notes

  • Declared in <string.h>; errno lives in <errno.h>.
  • Return pointer may alias static storage—do not modify or free it.
  • Read errno immediately after detecting failure.
  • Success paths may leave errno unchanged—only trust it after errors.
  • Multithreaded programs may prefer POSIX strerror_r.

⚡ Optimization

Error handling should run on exceptional paths only, so strerror cost rarely matters. Avoid calling it in tight success loops. Cache messages only if you copy them—never cache the raw pointer across later strerror calls.

Conclusion

strerror() bridges numeric errno values and human-readable diagnostics. Save the error code promptly, print the message, and use perror when a quick stderr line is enough.

Continue with strpbrk() for searching delimiter characters in strings.

💡 Best Practices

✅ Do

  • Save errno to a local variable right after failure
  • Include both <string.h> and <errno.h>
  • Print numeric code and message in logs for debugging
  • Copy the text if you need it after more library calls
  • Use perror for quick stderr diagnostics

❌ Don’t

  • Modify the string returned by strerror
  • Assume errno is zero on success without checking return values
  • Call strerror before verifying the function failed
  • Free the pointer returned by strerror
  • Rely on errno after unrelated successful calls

Key Takeaways

Knowledge Unlocked

Five things to remember about strerror()

Use these points when handling errors in C.

5
Core concepts
📝 02

Save early

Local int.

Pattern
🔢 03

Read-only

Static buf.

Return
📈 04

File I/O

fopen fail.

Use case
💬 05

vs perror

stderr.

Compare

❓ Frequently Asked Questions

strerror() takes an error number (such as the value in errno after a failed library call) and returns a pointer to a human-readable description of that error, for example "No such file or directory" for ENOENT.
Include <string.h> for strerror(). Include <errno.h> for errno and error constants like ENOENT and EINVAL. Many programs include both.
Read errno immediately after a function returns failure, before other library calls that might change errno. Store it in a local int variable if you need to call other functions before printing the message.
No. The returned pointer usually refers to static storage managed by the C library. Do not write to it. Later calls to strerror may reuse the same buffer.
strerror() returns a message string you can format with printf or logs. perror() writes a message directly to stderr, prefixed with your text, using the current errno value.
Plain strerror() may use a static buffer, so concurrent calls can race on some implementations. POSIX provides strerror_r for a thread-safe variant. For single-threaded beginner programs, strerror is fine.
Did you know?

C++ streams and some wrappers clear or ignore errno, but in pure C file APIs like fopen, read, and malloc (which sets errno on failure on POSIX), pairing return-value checks with strerror is the standard diagnostic pattern taught in systems programming courses.

Continue the String Functions Series

Turn error codes into messages with strerror(), then learn character-set search with strpbrk().

Next: strpbrk() →

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.

6 people found this page helpful