C assert() 表达式

C assert() expressions

C中的assert()函数工作原理对我来说就像一片黑暗的森林。根据此处的答案 ,您可以使用以下构造将自定义消息输出到您的断言:assert(retval == 1 && “retval is false”);,那么断言如何知道只有 二进制和 实际上包含一条消息 and 它不是表达式本身的一部分,而且它使用了哪些预编译器指令来揭示错误的来源?

消息是表达式的一部分,因此断言不会知道消息不是表达式的一部分。

retval == 1为假时,retval == 1 && (something)被计算为假而不计算(something)

retval == 1为真时,"retval is false"被求值,因为它被转换为一个有效的指针,它也会被求值为真,使得retval == 1 && "retval is false"被求值为真。

因此,retval == 1 && "retval is false"的真实性与retval == 1相同。

它不“知道”。该字符串是表达式的一部分,并且始终计算为 true。但是如果表达式的第一部分是 false,那么整个表达式也是 false,然后每个 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.

重点是我的,它表明消息实际上将包含消息字符串。类似于:

prog: some_file.c:16: some_func: Assertion `val == 0 && "The message text"' failed.

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 # 用字符串表示形式替换宏的参数。

#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 !@#$%^&*./;[]";

使用该运算符,您可以从宏中获取输入并将其作为字符串传递给您的函数:

#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();
   }
}

这样:

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宏也使用__FILE____LINE__predefined macros and __func__ to print a nice looking message where the assertion failed. And assert is usually implemented with conditional operator以便编译器可以更好地优化它。