宏`assert`,为什么不在全局范围内编译?
The macro `assert`, why doesn't it compile in the global scope?
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
明显的问题是:为什么 void
在 main
内部被接受但在全局范围内不被接受?
查看 clang 中的错误消息。
全局范围只能包含声明。断言宏扩展为表达式语句,不能出现在全局范围内。
assert()
宏是一个 运行-time 断言。它解析为代码,而不是变量声明/定义,因此在全局范围内是不允许的。
struct
定义之后的代码应该在一些外围函数中;照原样,它更像是伪代码,用于强化周围文本所表达的观点。
他们只是懒得在示例中的适当位置实际放置 int main()
。请注意,也没有 "run this code" 按钮——该片段不 应该 按原样编译。
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;
}
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
明显的问题是:为什么 void
在 main
内部被接受但在全局范围内不被接受?
查看 clang 中的错误消息。
全局范围只能包含声明。断言宏扩展为表达式语句,不能出现在全局范围内。
assert()
宏是一个 运行-time 断言。它解析为代码,而不是变量声明/定义,因此在全局范围内是不允许的。
struct
定义之后的代码应该在一些外围函数中;照原样,它更像是伪代码,用于强化周围文本所表达的观点。
他们只是懒得在示例中的适当位置实际放置 int main()
。请注意,也没有 "run this code" 按钮——该片段不 应该 按原样编译。
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;
}