C Macro Assert
# C Standard Library - ``: The `assert()` Macro
The `assert()` macro is a diagnostic tool provided by the C Standard Library, defined in the `` header file. It is used to verify assumptions made by the program at runtime. If a specified expression evaluates to false, `assert()` writes diagnostic information to the standard error stream (`stderr`) and terminates program execution.
`assert()` is highly valuable during the development, debugging, and testing phases of a project, helping developers catch logical errors early.
---
## Syntax and Declaration
To use the `assert()` macro, you must include the `` header file.
```c
#include
void assert(scalar expression);
```
### Parameters
* **`expression`**: This can be a variable, a comparison, or any valid C expression that evaluates to a scalar type (such as an integer, character, or pointer).
* If the expression evaluates to **true** (non-zero), `assert()` does nothing, and program execution continues normally.
* If the expression evaluates to **false** (zero), `assert()` triggers a failure.
### Behavior on Failure
When an assertion fails, `assert()` outputs a diagnostic message to `stderr` containing:
1. The text representation of the expression that failed.
2. The name of the source file (`__FILE__`).
3. The line number in the source file (`__LINE__`).
4. The name of the enclosing function (`__func__`, available since C99).
After printing the diagnostic message, it calls the `abort()` function to terminate the program immediately.
### Return Value
The `assert()` macro does not return any value.
---
## Code Example
The following example demonstrates how the `assert()` macro works in practice.
```c
#include
#include
int main()
{
int a;
char str;
printf("Enter an integer value: ");
scanf("%d", &a);
// Assert that the input integer must be greater than or equal to 10
assert(a >= 10);
printf("The integer entered is: %d\n", a);
printf("Enter a string: ");
scanf("%s", str);
// Assert that the string pointer is not NULL
assert(str != NULL);
printf("The string entered is: %s\n", str);
return 0;
}
```
### Sample Output
#### Case 1: Successful Execution (All assertions pass)
```text
Enter an integer value: 11
The integer entered is: 11
Enter a string: YouTip
The string entered is: YouTip
```
#### Case 2: Assertion Failure (Program terminates)
If you enter a value less than `10` (e.g., `5`), the first assertion fails:
```text
Enter an integer value: 5
a.out: main.c:12: main: Assertion `a >= 10' failed.
Aborted (core dumped)
```
---
## Disabling Assertions
In production or release builds, you may want to disable assertions to eliminate runtime overhead and improve performance. You can achieve this by defining the `NDEBUG` (No Debug) macro **before** including ``.
```c
#define NDEBUG
#include
```
When `NDEBUG` is defined, the preprocessor ignores all `assert()` statements, effectively turning them into empty statements (`((void)0)`). No code is generated for them, and no runtime checks are performed.
Alternatively, you can disable assertions globally during compilation using compiler flags (e.g., `-DNDEBUG` in GCC or Clang):
```bash
gcc -DNDEBUG main.c -o main
```
---
## Best Practices and Considerations
### When to Use `assert()`
* **Debugging and Testing**: Use assertions to catch programming errors and logical inconsistencies early in the development cycle.
* **Documenting Assumptions**: Assertions serve as active documentation. They clearly state the preconditions, postconditions, and invariants that the developer expects to be true at a specific point in the code.
* **Internal State Verification**: Use them to verify internal parameters that should never be invalid if the code is written correctly (e.g., checking if a private helper function received a non-null pointer).
### When NOT to Use `assert()`
* **Do Not Use for Runtime Error Handling**: `assert()` should not be used to handle expected runtime errors, such as user input validation, file-not-found errors, or memory allocation failures. These conditions should be handled gracefully using standard `if-else` error-handling routines.
* **Avoid Side Effects**: Never place expressions with side effects inside an `assert()` statement. Because assertions are disabled when `NDEBUG` is defined, any code inside the assertion will not run in the release build.
*β **Incorrect (Side effect inside assert):***
```c
assert(perform_critical_setup() == 1); // Will not execute if NDEBUG is defined!
```
*βοΈ **Correct:***
```c
int status = perform_critical_setup();
assert(status == 1); // The setup runs regardless of NDEBUG
```
YouTip