Read Source Code (0) -- assert. h in VC, two macros with more than 10 lines of code, which deserves scrutiny

Source: Internet
Author: User
/***
*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!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.