【发布时间】: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
显而易见的问题是:为什么void 在main 内部被接受,但在全局范围内却不被接受?
查看clang中的错误消息。
【问题讨论】:
-
那些
assert语句是可运行的逻辑,将它们放在main 或调用的某个函数中:coliru.stacked-crooked.com/a/80b9fb6afdf45e9b 创建s1和s2是可以的;它们是文件级变量,将在 main 之前初始化。 -
删除
assert你会仍然得到一个错误。您也不能在函数之外拥有reinterpret_cast<char*>(&s1)[2] = 'b'; // change 2nd byte。问题真的不在于assert。 -
@hvd 但是两个编译器都抱怨
assert宏扩展 -
旁白:您可以在全局范围内使用 static_assert,它适用于您在此处尝试执行的操作(即关于可以在编译时确定的事物的断言,例如 sizeof)。
-
@François-MarieArouet 抱歉不清楚。我的意思是问题不是特定于
assert。您在函数之外放置的 any 语句存在问题。碰巧assert被用在你的第一个全局语句中。