<errno.h> provides errno, a thread-local variable that functions set to indicate why they failed. Common codes: ENOENT (no file), EACCES (permission denied), EINVAL (invalid argument).
Only check errno immediately after a function that failed; successful calls may overwrite it, giving you meaningless noise.
This example checks errno to distinguish different error conditions after failed file operations.
// compile: gcc -o errnoexample errnoexample.c // run: ./errnoexample // description: interpret errno after system call failures #include <errno.h> #include <stdio.h> #include <string.h> #include <unistd.h> int main() { FILE* f = fopen("/nonexistent/file.txt", "r"); if (!f) { printf("fopen failed: %s (errno %d)\n", strerror(errno), errno); } if (access("/etc/shadow", R_OK) < 0) { printf("access denied: %s\n", strerror(errno)); } return 0; }