宏`断言`,为什么它不在全局范围内编译?

时间:2015-07-27 13:10:48

标签: c++ macros assert

cppreference中的此代码段无法编译。我理解这个问题与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中的错误消息。

3 个答案:

答案 0 :(得分:2)

全局范围只能包含声明。断言宏扩展为表达式语句,该语句不能出现在全局范围内。

答案 1 :(得分:1)

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

struct定义之后的代码应该在某个周围的函数内;因为它更像是伪代码,以强化周围文本的作用。

他们只是在实际在适当的地方放置一个int main()而烦恼。请注意,没有“运行此代码”按钮 - 该片段不是假设按原样编译。

答案 2 :(得分:0)

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;
}