YouTip LogoYouTip

C Macro Errno

## C Library Macro - `errno` The C library macro `errno` is a thread-local, modifiable lvalue set by system calls and some library functions in the event of an error to indicate what went wrong. `errno` is defined in the `` header file. It acts as an integer variable that stores error codes. When a standard library function encounters an error, it sets `errno` to an appropriate error code. Your program can then inspect this value to diagnose and handle the error gracefully. --- ## Declaration Below is the declaration for the `errno` macro: ```c extern int errno; ``` > **Note:** In modern C standards (C89 and later), `errno` is not required to be a simple `extern int` variable. It is typically defined as a macro that expands to a modifiable lvalue of type `int`. This allows it to be implemented using thread-local storage (TLS) to ensure thread safety. --- ## Parameters & Return Value * **Parameters:** None (it is a macro representing a variable/lvalue). * **Return Value:** It evaluates to an `int` representing the last error code. --- ## Workflow for Using `errno` To reliably use `errno` in your application, follow these steps: 1. **Include the Header**: Include `` in your source file. 2. **Reset `errno` (Optional but Recommended)**: Set `errno = 0` before calling a function that might fail. 3. **Call the Function**: Execute the library function or system call. 4. **Check the Return Value**: Verify if the function returned an error indicator (e.g., `NULL`, `-1`, or `EOF`). 5. **Inspect `errno`**: If an error occurred, check the value of `errno` to determine the specific error type. 6. **Handle the Error**: Take appropriate action based on the error code. --- ## Common `errno` Values The `` header defines symbolic constants for various error codes. Below are some of the most common standard error codes: | Constant | Description | | :--- | :--- | | `EPERM` | Operation not permitted | | `ENOENT` | No such file or directory | | `ESRCH` | No such process | | `EINTR` | Interrupted system call | | `EIO` | Input/output error | | `ENXIO` | No such device or address | | `E2BIG` | Argument list too long | | `ENOMEM` | Out of memory | | `EACCES` | Permission denied | | `EFAULT` | Bad address | | `EBUSY` | Device or resource busy | | `EEXIST` | File exists | | `EXDEV` | Cross-device link | | `ENODEV` | No such device | | `ENOTDIR` | Not a directory | | `EISDIR` | Is a directory | | `EINVAL` | Invalid argument | | `ENFILE` | File table overflow | | `EMFILE` | Too many open files | | `ENOTTY` | Not a typewriter (inappropriate ioctl for device) | | `ETXTBSY` | Text file busy | | `EFBIG` | File too large | | `ENOSPC` | No space left on device | | `ESPIPE` | Illegal seek | | `EROFS` | Read-only file system | | `EMLINK` | Too many links | | `EPIPE` | Broken pipe | --- ## Code Examples ### Example 1: Basic Usage of `errno` The following example demonstrates how to check `errno` when attempting to open a non-existent file. ```c #include #include #include // Note: Declaring 'extern int errno' manually is optional but historically common. // Including is the standard and preferred way. extern int errno; int main() { FILE *fp; // Attempt to open a file that does not exist fp = fopen("file.txt", "r"); if (fp == NULL) { // Print the numeric value of errno fprintf(stderr, "Value of errno: %d\n", errno); // Print the human-readable error message using strerror() fprintf(stderr, "Error opening file: %s\n", strerror(errno)); } else { fclose(fp); } return 0; } ``` #### Output If the file `file.txt` does not exist, compiling and running the program will produce the following output: ```text Value of errno: 2 Error opening file: No such file or directory ``` --- ### Example 2: Detailed Error Handling with `switch` This example demonstrates how to handle specific error codes differently using a `switch` statement. ```c #include #include #include int main() { // Attempt to open a file in read-only mode FILE *file = fopen("nonexistent_file.txt", "r"); if (file == NULL) { // Inspect the specific error code stored in errno switch (errno) { case EACCES: printf("Error: Permission denied\n"); break; case ENOENT: printf("Error: No such file or directory\n"); break; default: printf("Error opening file: %s\n", strerror(errno)); break; } return 1; } // File operations go here... fclose(file); return 0; } ``` --- ## Important Considerations ### 1. Thread Safety In modern, multi-threaded environments, `errno` is thread-safe. It is typically implemented using **Thread-Local Storage (TLS)**. This ensures that each thread has its own independent copy of `errno`, preventing race conditions where one thread overwrites the error code of another. ### 2. Initial and Success Values * **No Auto-Reset**: Standard library functions **never** reset `errno` to `0` upon successful execution. * **Stale Values**: If a function fails and sets `errno`, and then a subsequent function succeeds, `errno` will still contain the error code from the first failed function. * **Best Practice**: Always check the function's return value first to confirm an error occurred before inspecting `errno`. Alternatively, manually set `errno = 0` immediately before making the function call. ### 3. Cross-Platform Differences While many `errno` constants (like `EINVAL`, `ENOMEM`, `EACCES`) are standardized by POSIX and C standards, different operating systems (e.g., Linux, macOS, Windows) and C standard library implementations may define additional platform-specific error codes. Avoid relying on the exact numeric values of these constants, as they can vary across platforms. Always use the symbolic macros (e.g., `ENOENT`) instead of raw numbers (e.g., `2`). --- ## Best Practices for Error Handling 1. **Always Check Return Values First**: Do not inspect `errno` unless the function's return value explicitly indicates a failure (e.g., returns `NULL`, `-1`, or `EOF`). 2. **Clear `errno` Before Calls**: If you are calling a function that does not have a distinct error return value, set `errno = 0` before the call, and check if `errno != 0` immediately after. 3. **Use Helper Functions**: * **`strerror(int errnum)`**: Returns a pointer to the textual description string associated with the error code. * **`perror(const char *s)`**: Prints the string `s` followed by a colon, a space, and the textual description of the current `errno` value to `stderr`.
← C Macro EdomPhp Mysql Prepared Statements β†’