【问题标题】:The macro `assert`, why doesn't it compile in the global scope?宏`assert`,为什么不在全局范围内编译?
【发布时间】:2015-07-27 13:10:48
【问题描述】:

cppreference 中的这个 sn-p 无法编译。我知道问题与 assert 宏在全局范围内扩展的事实有关。也就是说,如果我们在函数中包含下面以assert(sieof(S)==8); 开头的部分代码,例如main(),则代码将起作用。

#include <cassert>
struct S {
    char c;  // 1 byte value
             // 3 bytes padding
    float f; // 4 bytes value
    bool operator==(const S& arg) const { // value-based equality
        return c == arg.c && f == arg.f;
    }
};
assert(sizeof(S) == 8);
S s1 = {'a', 3.14};
S s2 = s1;
reinterpret_cast<char*>(&s1)[2] = 'b'; // change 2nd byte
assert(s1 == s2); // value did not change

但我想了解为什么代码无法编译,如原始代码中所述。例如在VS2013中,宏定义如下:

    #define assert(_Expression) (void)( (!!(_Expression)) ||
             (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )

并且编译器抱怨以下错误消息:

error C2062: type 'void' unexpected

显而易见的问题是:为什么voidmain 内部被接受,但在全局范围内却不被接受?

查看clang中的错误消息。

【问题讨论】:

  • 那些assert 语句是可运行的逻辑,将它们放在main 或调用的某个函数中:coliru.stacked-crooked.com/a/80b9fb6afdf45e9b 创建s1s2 是可以的;它们是文件级变量,将在 main 之前初始化。
  • 删除assert 你会仍然得到一个错误。您也不能在函数之外拥有reinterpret_cast&lt;char*&gt;(&amp;s1)[2] = 'b'; // change 2nd byte。问题真的不在于assert
  • @hvd 但是两个编译器都抱怨assert 宏扩展
  • 旁白:您可以在全局范围内使用 static_assert,它适用于您在此处尝试执行的操作(即关于可以在编译时确定的事物的断言,例如 sizeof)。
  • @François-MarieArouet 抱歉不清楚。我的意思是问题不是特定于assert。您在函数之外放置的 any 语句存在问题。碰巧assert 被用在你的第一个全局语句中。

标签: c++ macros assert


【解决方案1】:

全局范围只能包含声明。 assert 宏扩展为一个表达式语句,它不能出现在全局范围内。

【讨论】:

  • AFAICT,可以在全局范围内调用函数。例如,这是一个有效的代码:int f() { return 5; } int a = f();
  • @François-MarieArouet:你是什么意思?
  • @DevSolar 请参阅我上面给出的示例。
  • @françois-marie:这是带有初始化器的声明,而不是表达式语句。
  • @François-MarieArouet 全局对象可以在全局范围内使用函数进行初始化,但您不能在全局范围内运行任意代码。为什么?那么编译器如何知道何时运行代码呢?当你定义一个全局对象时,你知道代码在对象初始化时运行
【解决方案2】:

assert() 宏是一个运行时 断言。它解析为代码,而不是变量声明/定义,因此在全局范围内是不允许的。

struct 定义之后的代码应该在一些周围的函数中;按原样,它更像是伪代码来强化周围文本的意义。

他们只是懒得在示例中的适当位置实际放置int main()。请注意,也没有“运行此代码”按钮 -- sn-p 不应该按原样编译。

【讨论】:

    【解决方案3】:

    assert() 必须在函数中:

    #include <cassert>
    struct S {
        char c;  // 1 byte value
                 // 3 bytes padding
        float f; // 4 bytes value
        bool operator==(const S& arg) const { // value-based equality
            return c == arg.c && f == arg.f;
        }
    };
    int main(){
        assert(sizeof(S) == 8);
        S s1 = {'a', 3.14};
        S s2 = s1;
        reinterpret_cast<char*>(&s1)[2] = 'b'; // change 2nd byte
        assert(s1 == s2); // value did not change
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-01-01
      • 2015-01-30
      • 1970-01-01
      • 1970-01-01
      • 2015-04-07
      • 2016-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多