Search code examples
cassert

C assert() expressions


assert() function working principle in C for me is like a dark forest. according to this answer here https://stackoverflow.com/a/1571360, you can use the following construction to output the custom message to your assertion: assert(retval == 1 && “retval is false”);, so how does assert know that the expression with just a binary and actually contains a message and that it is not the part of the expression itself, and, also, which precompiler directives it uses in order to reveal the error's origin?


Solution

  • how does assert know that the expression with just a binary and actually contains a message and that it is not the part of the expression itself?

    Operator # replaces the parameter of a macro by it's string representation.

    #define TOSTRING(parameter)  #parameter
    //                            ^^^^^^^^^ - always followed by a macro parameter
    //                           ^ - # operator
    
    const char *a = TOSTRING(almost     anything does not matter !@#$%^&*./;[]);
    // expands to:
    // const char *a = "almost anything does not matter !@#$%^&*./;[]";
    

    Using that operator, you can take the input from a macro and pass it to your function as a string:

    #define myassert(expression)   myassert_handle(expression, #expression)
    
    void myassert_handle(bool expression_result, const char *exprsesion_string) {
       if (expression_result == false) {
           fprintf(stderr, "Och no: expression %s failed!\n", exprsesion_string);
           abort();
       }
    }
    

    That way:

    myassert(retval == 1 && "retval is false");
    // expands to
    myassert_handle(retval == 1 && "retval is false", "retval == 1 && \"retval is false\"");
    // and if the expression will fail, it will print: 
    // Och no: expression retval == 1 && "retval is false" failed!
    

    Assert macro also uses __FILE__ and __LINE__ predefined macros and __func__ to print a nice looking message where the assertion failed. And assert is usually implemented with conditional operator so that compiler can optimize it better.