errno & perror()
Many standard library functions signal failure through their return value alone (like NULL or -1), but that doesn't tell you why they failed. To fill that gap, C provides a global variable, errno, declared in <errno.h>, that many library functions set to a specific error code when they fail.
What errno Is
errno is an integer (in modern C, typically a thread-local variable behind the scenes) that gets set to a nonzero value describing the last error when a function fails. Common values include ENOENT (no such file or directory), EACCES (permission denied), and ENOMEM (out of memory).
Check errno Only Immediately After a Failed Call
#include <stdio.h>
#include <errno.h>
int main(void) {
FILE *file = fopen("does_not_exist.txt", "r");
/* Correct order: check the return value FIRST, then consult errno. */
if (file == NULL) {
printf("fopen failed, errno = %d\n", errno);
}
return 0;
}perror(): Human-Readable Error Messages
perror(message) prints message, followed by a colon and a human-readable description of the current errno value, to stderr. It's the quickest way to report "something failed, and here's why" without manually translating error codes yourself.
#include <stdio.h>
int main(void) {
FILE *file = fopen("does_not_exist.txt", "r");
if (file == NULL) {
perror("fopen"); /* e.g. prints: fopen: No such file or directory */
return 1;
}
fclose(file);
return 0;
}strerror(): Getting the Message as a String
Sometimes you want the human-readable message as a string, rather than having it printed directly (for example, to embed it in a log line with more context). strerror(errno) returns a pointer to that message.
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void) {
FILE *file = fopen("does_not_exist.txt", "r");
if (file == NULL) {
fprintf(stderr, "Failed to open file: %s\n", strerror(errno));
return 1;
}
fclose(file);
return 0;
}Worked Example: Reporting Why a File Failed to Open
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void) {
const char *filename = "/root/protected-or-missing.txt";
errno = 0; /* optional: reset explicitly before the call, for clarity */
FILE *file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "Could not open \"%s\": %s (errno %d)\n",
filename, strerror(errno), errno);
return 1;
}
printf("File opened successfully.\n");
fclose(file);
return 0;
}perror vs strerror
Function | Output | When to use |
|---|---|---|
perror(msg) | Writes directly to stderr | Quick, simple error reporting to the console |
strerror(errno) | Returns a string you control | Building a custom log message or error format |