Reputation: 74
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?
Upvotes: 2
Views: 1074
Reputation: 142025
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.
Upvotes: 2
Reputation: 18381
It doesn't "know". The string is a part of the expression and always evaluates to true
. But if the first part of the expression is false
, then the whole expression is false
as well, and then per man 3 assert
:
If expression is false (i.e., compares equal to zero), assert() prints an error message to standard error and terminates the program by calling abort(3). The error message includes the name of the file and function containing the assert() call, the source code line number of the call, and the text of the argument; something like:
prog: some_file.c:16: some_func: Assertion `val == 0' failed.
The emphasis is mine, and is showing that the message will in fact contain the message string. Similar to:
prog: some_file.c:16: some_func: Assertion `val == 0 && "The message text"' failed.
Upvotes: 3
Reputation: 75062
The message is part of the expression, so the assert won't know that the message is not the part of the expression.
When retval == 1
is false, retval == 1 && (something)
is evaluated as false without evaluating (something)
.
When retval == 1
is true, "retval is false"
is evaluated and, because it is converted to a valid pointer, it will also be evaluated as true, making retval == 1 && "retval is false"
evaluated as true.
Therefore, the trueness of retval == 1 && "retval is false"
is the same as retval == 1
.
Upvotes: 3