【问题标题】:C assert() expressionsC 断言()表达式
【发布时间】:2020-07-22 17:46:30
【问题描述】:

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

【问题讨论】:

  • assert 不是函数,而是宏。
  • 注意不是",可能是复制+粘贴造成的。

标签: c assert


【解决方案1】:

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

retval == 1 为假时,retval == 1 && (something) 被评估为假而不评估(something)

retval == 1 为真时,"retval is false" 被评估,因为它被转换为有效指针,它也将被评估为真,使retval == 1 && "retval is false" 被评估为真。

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

【讨论】:

    【解决方案2】:

    它不“知道”。该字符串是表达式的一部分,并且始终计算为true。但是如果表达式的第一部分是false,那么整个表达式也是false,然后是man 3 assert

    如果表达式为假(即比较等于零),assert() 将错误消息打印到标准错误并终止程序 通过调用 abort(3)。错误消息包括文件名 和包含 assert() 调用的函数,源代码行 调用的编号,和参数的文本;类似于:

          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.
    

    【讨论】:

      【解决方案3】:

      assert 怎么知道只有一个二进制的表达式实际上包含一条消息,并且它不是表达式本身的一部分?

      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__func__ 在断言失败的地方打印一条漂亮的消息。而assert通常是用conditional operator实现的,这样编译器可以更好地优化它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-11
        • 1970-01-01
        • 1970-01-01
        • 2010-09-15
        • 2023-03-17
        相关资源
        最近更新 更多