The macro `assert`, why doesn't it compile in the global scope?

This snippet in cppreference doesn't compile. I understand the problem has to do with the fact that the assert macro is expanded in the global scope. That is, if we include the part of code below, starting with assert(sieof(S)==8); inside a function, like main() for example, the code will work.

#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

But I want to understand why the code doesn't compile, as stated in the original code. For example in VS2013, the macro is defined as follows:

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

and the compiler complains with the following error message:

error C2062: type 'void' unexpected

The obvious question is: why is the void accepted inside main but not in the global scope?

See the error messages in clang.

Upvotes: 2

Views: 1444

Answers (3)

DevSolar
DevSolar

Reputation: 70283

The assert() macro is a run-time assertion. It resolves to code, not a variable declaration / definition, and as such is not permitted at global scope.

The code after the struct definition is supposed to be inside some surrounding function; as-is it's more like pseudo-code to reinforce the point the surrounding text is making.

They just didn't bother with actually putting an int main() in the example at the appropriate place. Notice that there is no "run this code" button either -- that snippet is not supposed to be compiled as-is.

Upvotes: 2

Liyuan Liu
Liyuan Liu

Reputation: 172

assert() must in function like:

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

Upvotes: 1

rici
rici

Reputation: 241771

Global scope can only contain declarations. The assert macro expands to an expression statement, which cannot appear at global scope.

Upvotes: 3

Related Questions