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.
Fundamentals
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.
Foundation
📝 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.
Cheat Sheet
⚡ Quick Reference
Constant
Typical meaning
Example message
ENOENT
File not found
No such file or directory
EACCES
Permission denied
Permission denied
ENOMEM
Out of memory
Cannot allocate memory
EINVAL
Invalid argument
Invalid argument
usage
strerror(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
Hands-On
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.
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;
}
📤 Output (code varies by OS):
Failed (code 2): No such file or directory
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.
[ERROR] fopen failed: No such file or directory (code 2)
How It Works
A helper reads errno immediately and formats action, message, and numeric code—useful across a project for uniform error reporting.
Applications
🚀 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.
Important
📝 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.
Performance
⚡ 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.
Wrap Up
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.
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
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about strerror()
Use these points when handling errors in C.
5
Core concepts
⚠️01
errno → text
Readable.
Basics
📝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.