/***
*assert.h - define the assert macro
****/
#include <crtdefs.h>
// Remove possible assert definitions to ensure that the assert is not defined
// But according to the test, the # defines in the "back" will overwrite the previous # defines
// It is worth learning!
#undef assert
// If ndebug is defined, disable the assert macro.
// In the release mode, ndebug is automatically defined to cancel assert assertions, that is, it is defined as a no-op
#ifdef NDEBUG
#define assert(_Expression) ((void)0)
// Why is it defined as (void) 0, rather than "blank ". Explanation:
// 1. (void) 0) is a complete expression, but "blank" is not
// 2. For example, "assert (1 = 2), 12;" is an expression. If assert (...) is defined as "blank", compilation fails.
// 3. (void) 0) is a no-OP expression. The compiler will ignore them (it should not generate code for it)
// 4. To put it bluntly, it is shut up the compiler to shut up the compiler!
# Else // ndebug is not defined. In debug mode, assert is defined as a special debugging function.
# Ifdef _ cplusplus // if it is a CPP environment, pay attention to the link to the C function!
extern "C" {
#endif
_CRTIMP void __cdecl _wassert(_In_z_ const wchar_t * _Message,
_In_z_ const wchar_t *_File, _In_ unsigned _Line);
//_In_z - nullterminated 'in' parameters.
//_In_ - input (pointer) parameter
// _ Cribd-"blank" or if _ DLL is defined, replace it with _ declspec (dllimport)
#ifdef __cplusplus
}
#endif
// A line feed is provided for ease of reading.
#define assert(_Expression) \
(void)( (!!(_Expression)) || \
(\
_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), \
0\
) \
)
// | Short circuit!
// If !! (_ Expression) the result is true, so the subsequent code will not be executed at all. If it is false, it will be executed!
// Return value adapter:
// The _ wassert function is void. How can it be used | !, Easy to do: Add ", 0", so that the return value of the entire expression is 0!
// However, assert should not return any value, and then convert the result of the entire expression to void, which is the whole expression. Note the parentheses in the outermost layer!
// Macro string connection method: # (token-pasting operator) and # (stringizing operator)
// _ Crt_wide (# _ expression)-l ### _ expression (long string, which is stored in 2 bytes)
// _ File _ and _ line __
//"!! "Highlights
// Start with _ w, which is a unicode version. Of course, there is another _ assert version function,
// The definition of track_wassert finds that it actually does a lot of things, such as stderr and buffer processing,
// The Library itself also provides a comment:
/*
* Build the assertion message, then write it out. The exact form
* depends on whether it is to be written out via stderr or the
* MessageBox API.
*/
// In VC, if the assert fails, the following format is displayed:
// Assertion failed: <expr>, file <filename>, line <lineno>
// Finally, a message dialog box is provided for the user to select
//if (nCode == IDABORT)
//{ raise(SIGABRT);
// _exit(3);}
//if (nCode == IDRETRY)
//{ __debugbreak();
// return;}
//if (nCode == IDIGNORE)
// return;
// Note that the last line of the _ wassert function is the call of the abort () function!
// Exit (): gentle!
// Abort (): violent! Close the current process directly. No matter what the file resource is!
#endif /* NDEBUG */
The following is the display of assert's MessageBox. The specific code can be viewed in assert. C.
After reading the source code of assert. H, I did get a lot of results. In fact, this was a very accidental reading. I had a deep understanding of the debug function of VC ++ 2010 and thought of assert.
Summary: Conditional compilation, linking, macro usage, concealed returned values, and inherent assert behaviors ......
The simpler test code below is a small case. Of course, it does not make much sense.
I have to mention that in writing solid code, the semantic explanation of the Application of assert is very detailed and in-depth, and the book is old, but it means Judah. I 've seen it, but I forgot about it...
void output(const char* msg)
{
cout << msg << endl;
}
#define test(exp) (void) ((!!(exp)) || (output("hello"), 0))
Of course, the source code of VC is not Copyleft, but must be declared. It is just for learning. Finally, I want to complain: so many # defines !! However, it is a blessing to be able To toss.
I am a little cainiao myself. When I first got on the road, there must be a lot of explanations that are problematic. You are welcome to correct me and learn from each other!