Every time I write a summary I think it is a headache, because I know the abstract is really important, it almost directly determines the number of readers. May have spent 962 of tigers to write out something that because of the failure of the summary, because the vast majority of readers read the article before the summary, if they found that the summary "does not correspond", there is no special features and attractive places, then the light is the use of Islands method read the full text, heavy on the article sentenced to "death penalty", Although the quality of an article can not be measured by a summary, it is often used by readers to measure the quality of an article, thus becoming a key factor in the number of readers of the article. Let's say to the assertion that if you're learning C for general purposes and for exams, I think very few people will use assertions in their code, and some may never have used assertions before. So what does the assertion's use actually bring to our code? I have tried to explain the use of assertions I understand as much as possible, and I hope that the assertions I have made here will help you to use the assertions flexibly in your code later.
Before we explain, let's make a basic introduction to assertions, so that you have a general idea of assertions. When writing engineering code in C, we always examine a hypothetical condition that is used to capture these assumptions in code and can be viewed as an advanced form of exception handling. Assertions are represented as Boolean expressions, and programmers believe that the expression value is true at a particular point in the program. Assertion validation can be enabled and disabled at any time, so assertions can be enabled at test time, and assertions are disabled at deployment time. Also, after the program is put into operation, the end user can reactivate the assertion when they encounter a problem. It can quickly detect and locate software problems, and automatically alarm the system errors. Asserts can be hidden deep in the system, and other methods are very difficult to find the problem can be used to locate the assertion, so as to shorten the software problem location time, improve the system's testability. In practical application, the assertion can be designed flexibly according to the specific circumstances.
With the above explanation we have a general idea of assertions, so let's take a look at the use of Assert macros in the code in C language.
Prototype definition:
void assert (int expression);
The stereotype of an Assert macro is defined in <assert.h> to evaluate the expression expression first, and if the expression value is False (that is, 0), it prints an error message to stderr, and then by calling Abort To terminate the program operation.
Let's take a look at a piece of code:
Copy Code code as follows:
#include <stdio.h>
#include <assert.h>
int main (void)
{
int i;
I=1;
ASSERT (i++);
printf ("%d\n", I);
return 0;
}
The results of the operation are:
Look at the results of the run, because we given the initial value of 1, so use ASSERT (i++), the statement is not an error, and then execute the i++, so the output value of the subsequent print statement is 2. If we change the initial value of I to 0, the following error is returned.
Assertion failed:i++, file E:\fdsa\assert2.cpp, line 8
Press any key to continue
Do you find that you can locate the error point quickly according to the prompt?! Since assert is so easy to locate error points, it seems that it is necessary to skillfully use it in the code, but the use of everything is a rule, the use of Assert is no exception.
Assertion statements are not always executed, can be masked or enabled, and this requires that the assert does not affect the functionality of our own code, whether it is masked or enabled, so that we used an assert (i++) in the code just now; Because once we disable the assert,i++ statement will not be executed, for the next I value of the use will be a problem, so for such a statement we should be separate to achieve, write the following two sentences to replace, assert (i); i++, so this has a corresponding requirement for the use of assertions, so where do we normally use assertions? Mainly reflected in a few aspects:
1. Asserts can be placed where the program is expected to not arrive. (such as assert (0);)
2. Use the assertion test method to execute the precondition and the post condition.
3. Use assertions to check the invariant state of a class to ensure that, in any case, the state of a variable must be satisfied. (such as a variable range of variables)
For the above preconditions and post conditions may be a reader is not very familiar with, then look at the following explanation you understand.
Pre-Conditional assertion: Attributes that must be available before code executes
Post-Conditional assertion: Attributes that must be available after code execution
Invariant assertion: Features that cannot be changed before and after code execution
Of course, in the process of using the assertion there will be some things we should pay attention to and develop some good habits, such as:
1. Each assert examines only one condition, because when multiple conditions are checked, if the assertion fails, we cannot intuitively determine which condition failed
2. You cannot use statements that alter the environment, just as our code above changes the I variable, which is not possible in the actual code writing process.
3.assert and the following statements should be empty line to form a logical and visual sense of consistency, but also a good programming habits, so that the code has a visual aesthetic
4. In some places, assert cannot replace conditional filtration
5. Check the validity of incoming parameters at the entrance of function parameters
6. Assertion statements may not have any boundary effects
There are so many words on it, seems very boring, but there is no way, we can not be quick, or to adhere to read the text Description section, so that in the following analysis of the code we can quickly understand why there is such a problem, but also in their own code when the skilled use of assert, It's great for debugging your code, especially if you're using C to do a project, and if you can use assert in your code properly, you can create more stable, better quality, and less error-prone code. You can use assertions when you want to break the current operation with a value of false. Unit tests must use assertions, and in addition to type checking and unit testing, assertions provide an excellent way to determine whether a variety of attributes are maintained in the program. All good programmers can use assert in their own code and write high-quality code.
Said the assert so much a bit, of course, to talk about its shortcomings.
The disadvantage of using assert is that frequent calls can greatly affect the performance of your program and add additional overhead. So after debugging, you can disable an assert call by inserting a #define NDEBUG before the statement that contains the #include.
Next, analyze the following section of code:
Copy Code code as follows:
#include <stdio.h>
#define Ndebug
#include <assert.h>
int copy_string (char From[],char to[])
{
int i=0;
while (To[i++]=from[i]);
printf ("%s\n", to);
return 1;
}
int main ()
{
Char str[]= "This is a string!";
Char dec_str[206];
printf ("%s\n", str);
ASSERT (Copy_string (STR,DEC_STR));
printf ("%s\n", dec_str);
return 0;
}
The results of the operation are:
At the beginning of the above code we dropped the #define NDEBUG, so we enabled the Assert,main function to use ASSERT (Copy_string (STR,DEC_STR)) to implement the invocation of the copy_string function. In the copy_string function we used a return 1, so the final function call result is equivalent to assert (1), so then continue to execute the print statement below the Assert, and finally successfully print out three output statements, if we open the comment section of the beginning, The result can only be a successful output from the starting part of a print statement.
Now that we're all talking about assert macros, just to teach you how to use Assert macros, how do we go about implementing our assertions?
Next, let's look at another piece of code:
Copy Code code as follows:
#include <stdio.h>
#undef _exam_assert_test_//disabled
#define _EXAM_ASSERT_TEST_//Enable
#ifdef _EXAM_ASSERT_TEST_//Enable assertion testing
void Assert_report (const char * file_name, const char * function_name, unsigned int line_no)
{
printf ("\n[exam]error file_name:%s, function_name:%s, line%u\n",
file_name, Function_name, line_no);
}
#define ASSERT_REPORT (condition) \
do{\
if (condition) \
NULL; \
else \
Assert_report (__file__, __func__, __line__); \
}while (0)
#else//Disable assertion test
#define ASSERT_REPORT (condition) NULL
#endif/* End of ASSERT */
int main (void)
{
int i;
i=0;
ASSERT (i++);
Assert_report (i);
printf ("%d\n", I);
return 0;
}
The results of the operation are as follows:
[EXAM] Error file_name:assert3.c, Function_name:main, line 29
0
Attentive readers will find that we have not used assertions to end the execution of the current program, so in the assertion below printf successfully prints out the current value of I, of course, we can also make the appropriate changes, in the assertion of the discovery error, then call Abort (), so that the currently executing program terminates abnormally, Modified as follows:
Copy Code code as follows:
#include <stdio.h>
#include <stdlib.h>
#undef _exam_assert_test_//disabled
#define _EXAM_ASSERT_TEST_//Enable
#ifdef _EXAM_ASSERT_TEST_//Enable assertion testing
void Assert_report (const char * file_name, const char * function_name, unsigned int line_no)
{
printf ("\n[exam]error file_name:%s, function_name:%s, line%u\n",
file_name, Function_name, line_no);
Abort ();
}
#define ASSERT_REPORT (condition) \
do{\
if (condition) \
NULL; \
else \
Assert_report (__file__, __func__, __line__); \
}while (0)
#else//Disable assertion test
#define ASSERT_REPORT (condition) NULL
#endif/* End of ASSERT */
int main (void)
{
int i;
i=0;
ASSERT (i++);
Assert_report (i);
printf ("%d\n", I);
return 0;
}
The results of the operation are as follows:
[EXAM] Error file_name:assert3.c, Function_name:main, line 31
Aborted
The next print statement is not executed at this time. By looking at our own implementation, we know that the assertions we write ourselves can get more information than we call assert macros, mainly because our own assertions are more flexible and can print out different information according to our own needs. It is also possible to use different assertions for different types of errors or warning messages, which are often used in engineering code. If you read my code carefully while you're looking at the results of the code, you will find that I have used a do{}while (0) in the macro definition and what is the benefit of using it, perhaps not reflected in the above code, then we look at the following code you know.
Copy Code code as follows:
#include <stdio.h>
void print_1 (void)
{
printf ("print_1\n");
}
void print_2 (void)
{
printf ("print_2\n");
}
#define PRINTF_VALUE () \
Print_1 (); \
Print_2 (); \
int main (void)
{
int i=0;
if (i==1)
Printf_value ();
return 0;
}
Run Result:
Or back up the article description, in case the picture opened failed to cause confusion to the reader.
Print_2
Press any key to continue
Read the results of the above may be the reader will be very puzzled why the above error?! If the condition of the IF statement is not satisfied, then the Print_value () function should not be called Ah, how can print it. If we replace the above Printf_value () with print_1 (); Print_2 (), it is clear that the IF statement does not function in this case simply by not calling Print_1 (); and Print_2 (), in addition to control, so there are the results of the above, some readers may immediately think we add a {} not good, here is indeed a {} Is OK, because here is a special case, there is no else statement, if we use {} in the above macro definition, add the Else statement and then look at the code.
Copy Code code as follows:
#include <stdio.h>
void print_1 (void)
{
printf ("print_1\n");
}
void print_2 (void)
{
printf ("print_2\n");
}
#define PRINTF_VALUE () \
{ \
Print_1 (); \
Print_2 ();}
int main (void)
{
int i=0;
if (i==1)
Printf_value ();
Else
printf ("Add else word!!!");
return 0;
}
Seemingly correct code, we compile the following error:
Error C2181:illegal else without matching if
Why is there such a mistake? Since we write the C language code, it is customary to add a semicolon after each statement, in which we add a semicolon after the Printf_value () statement, which is precisely because the semicolon does not have a corresponding if, so the compile error occurs. But if we use Do{}while (0) We don't have these problems, so we should learn to use Do{}while (0) in a macro definition when writing code.
This is the end of the explanation for the
C language assertion content. The above content has given the C language code in the process of the assertion of the more detailed use, which use our own implementation of the assertion is a relatively classic assertion design method, the reader can later write the C language code in the process of reference. Due to my limited level, the article in the wrong or wrong place is unavoidable, earnestly hope that the reader criticized. Readers are also welcome to explore the relevant content, if you are willing to exchange words please leave your valuable comments.