How perror Translates errno into Error Messages in C

The perror function in C provides an efficient way to output human-readable explanations of system-level errors. When a system call or standard library function fails, it typically reports failure and sets a global integer variable named errno to represent the specific error condition. The perror function takes this numeric code, maps it internally to a predefined textual description, and prints the result directly to the standard error stream (stderr).

The Role of errno

The C standard defines errno (accessible via <errno.h>) as an integer variable—implemented as a thread-local variable in modern multithreaded environments—that stores an error number when an operation fails. For example, attempting to open a nonexistent file with fopen sets errno to ENOENT, which corresponds to a specific integer code (often 2 on POSIX systems).

Because numeric codes are difficult for users and developers to interpret quickly, standard C libraries maintain a centralized database or internal array of corresponding error strings.

The Internal Translation Mechanism

When perror is invoked, it executes the following steps to translate the error code:

  1. Reading errno: The function evaluates the current value of the errno variable at the moment of invocation.
  2. Looking Up the Text: The standard C library maintains an internal catalog of error strings. Conceptually, this behaves like the strerror function. In older UNIX implementations, this mapping was exposed through an array named sys_errlist[] indexed by sys_nerr. Modern C standard libraries (such as glibc or musl) use localized message catalogs. The function matches the integer value of errno against this catalog to retrieve the corresponding null-terminated string (e.g., mapping ENOENT to "No such file or directory").
  3. Handling Locale: Modern implementations factor in the program's current locale setting (specifically the LC_MESSAGES category). If configured, perror retrieves localized descriptions suited to the user's language and region. If the numeric value does not correspond to a recognized error, it falls back to a generic message such as "Unknown error: <number>".

Output Formatting

The function signature for perror is:

void perror(const char *s);

During execution, perror formats its output directly to stderr:

  • If the parameter s is not NULL and does not point to an empty string, perror first prints the custom string pointed to by s, followed by a colon and a space (:).
  • It then prints the translated error string obtained from the system catalog.
  • Finally, it appends a newline character (\n) and flushes the stream.

If s is NULL or points to an empty string, perror only outputs the translated error message followed by a newline, omitting the prefix and the colon. Through this process, perror eliminates the need for manual error code lookups and ensures standard error reporting across C applications.