When writing project code in C language, we often check certain assumptions, and assertions are used to capture these assumptions in the code. Assertions can be seen as a high-level form of exception handling. An assertion is represented as a boolean expression that programmers believe to be true at a specific point in the program. Assertions can be enabled and disabled at any time, allowing them to be enabled during testing and disabled during deployment. Similarly, after the program is running, end users can re-enable assertions when encountering issues. They can quickly identify and locate software problems while automatically alerting for system errors. Assertions can help locate issues that are deeply hidden in the system and difficult to detect by other means, thereby shortening the time to identify software problems and improving the testability of the system. In practical applications, assertions can be flexibly designed according to specific situations.
With the above explanation, we have a general understanding of assertions. Next, let’s take a look at the usage of the assert macro in C language code.
Prototype definition:
void assert(int expression);
The prototype definition of the assert macro is in <assert.h>, and its function is to first evaluate the expression. If the value of the expression is false (i.e., 0), it prints an error message to stderr and then terminates the program by calling abort.
Now, let’s look at a piece of code:
#include <stdio.h>
#include <assert.h>
int main(void)
{
int i;
i=1;
assert(i++);
printf(“%d\n”, i);
return 0;
}
The output is:

Looking at the output, since we set the initial value of i to 1, using the assert(i++); statement does not cause an error, and thus i++ is executed, resulting in the printed value being 2. If we change the initial value of i to 0, the following error will occur.
Assertion failed: i++, file E:\fdsa\assert2.cpp, line 8
Press any key to continue
Did you notice that the prompt allows us to quickly locate the error point?! Since assert makes it easy to locate error points, it is indeed necessary for us to become proficient in using it in our code. However, the use of anything comes with rules, and assert is no exception.
Assertion statements do not always execute; they can be disabled or enabled. This means that assert should not affect the functionality of our code whether it is disabled or enabled. Therefore, the statement assert(i++); is inappropriate because if we disable assert, the i++ statement will not be executed, leading to issues with subsequent uses of i’s value. Instead, we should implement this in two separate statements: assert(i); i++;. Thus, there are corresponding requirements for the use of assertions. When should we generally use assertions? They are mainly reflected in the following aspects:
1. Assertions can be placed in places where the program is not expected to reach under normal circumstances (e.g., assert(0);).
2. Use assertions to test the preconditions and postconditions of methods.
3. Use assertions to check class invariants, ensuring that under any circumstances, a certain variable’s state must be satisfied (e.g., the range of a variable’s change).
For the above preconditions and postconditions, some readers may not be very familiar, so let’s look at the following explanations to understand.
Precondition assertion: Characteristics that must be present before code execution.
Postcondition assertion: Characteristics that must be present after code execution.
Invariant assertion: Characteristics that cannot change before and after code execution.
Of course, there are some matters we should pay attention to while using assertions and cultivate good habits, such as:
1. Each assert should only check one condition because when checking multiple conditions simultaneously, if the assertion fails, we cannot intuitively determine which condition failed.
2. Do not use statements that change the environment, just like the code above changed the variable i. This should not be done in actual coding.
3. There should be a blank line after assert and the following statement to create logical and visual consistency; this is also a good programming habit that gives the written code a sense of visual beauty.
4. In some cases, assert cannot replace conditional filtering.
5. Check the legality of incoming parameters at the entrance of function parameters.
6. Assertion statements should not have any boundary effects.
All the above text may seem tedious, but we cannot rush for quick results; we must first persist in reading the descriptive part so that we can quickly understand why such problems arise during the code analysis process, and we can use assert proficiently when writing our code, bringing great convenience to our debugging. Especially when using C language for engineering projects, if you can reasonably use assert in your code, it will help you create more stable, higher quality, and less error-prone code. When it is necessary to interrupt the current operation when a value is FALSE, assertions can be used. Unit tests must use assertions; besides type checking and unit tests, assertions also provide an excellent way to ensure various features are maintained in the program. Any excellent programmer can effectively use assert in their code to write high-quality code.
Having talked about the advantages of assert, it is also necessary to mention its disadvantages.
The disadvantage of using assert is that frequent calls can greatly affect the performance of the program and increase overhead. Therefore, after debugging is completed, assertions can be disabled by inserting #define NDEBUG before the include statements.
Next, let’s analyze a piece of code: the full text can be seen in the original article.
