Because C is a low-level language, it doesn't automatically "throw" an error when something goes wrong. Instead, most C functions return a special value (like -1 or NULL) to signal a problem. It is the programmer's job to check these values and decide what to do next.
errno Variable
When a standard library function fails, it typically sets a global integer variable called errno (Error Number). This variable holds a code that represents the specific reason for the failure.
To use errno, you must include the <errno.h> header.
sqrt()).perror() and strerror()
Since numeric codes like "2" or "33" aren't helpful to users, C provides two functions to translate errno into a human-readable string.
errno.<string.h>).EXIT_SUCCESS vs EXIT_FAILURE
When a program terminates, it sends an exit status to the Operating System. By convention, 0 means success, and any non-zero value means an error occurred.
In <stdlib.h>, two constants are defined to make this explicit:
EXIT_SUCCESS (equivalent to 0)EXIT_FAILURE (equivalent to 1)
C does not have a specific errno for division by zero; on many systems, this will simply crash the program with a "Floating Point Exception." You must check the divisor manually before performing the operation.
Professional C developers follow these strategies to build robust software:
| Strategy | Description |
|---|---|
| Return Value Check | Always check if malloc returned NULL or if fopen failed. |
Use stderr |
Print error messages to the "Standard Error" stream instead of stdout. |
| Graceful Exit | Free memory and close open files before calling exit(). |
Reset errno |
Since errno is never reset to 0 by the system, clear it manually (errno = 0;) before a critical call. |
For errors that are more severe (like Segment Faults or hitting Ctrl+C), C uses Signals. Using <signal.h>, you can write a "signal handler" function to catch these events and shut down the program cleanly.