为什么这个数组的 sizeof() 是非法的?

Why is sizeof() of this array illegal?

我有以下数组:

static std::pair<const Type, const size_t> typemap_[];

定义为

std::pair<const talos::Message::Type, const size_t> talos::Message::typemap_[8] = {
{ talos::Message::Type::Empty, typeid(int).hash_code() },
{ talos::Message::Type::Keyboard , typeid(int).hash_code() },
...

这是为什么

sizeof(typemap_);

给出编译时错误

Error C2070 'std::pair []': illegal sizeof operand

即使这样

sizeof(typemap_[0]);

合法且数组大小固定?

类型定义为:

enum class Type {...} 

如果当前翻译单元中没有static std::pair<const Type, const size_t> typemap_[];定义,只有这个声明,则编译器无法可能知道它的大小,因为声明中没有大小。

编译器似乎缺少 typemap_ 变量的定义。由于它是静态的,您可能将其隐藏在其中一个源文件中。

如果您将现在拥有的所有内容都放入同一个源中,该解决方案就会起作用。例如:

enum class Type {None, Some} ;
static std::pair<const Type, const size_t> typemap_[] = {
    { Type::None, typeid(int).hash_code() },
    { Type::Some , typeid(int).hash_code() },
};

int main() {
    std::cout << "sizeof: " << sizeof(typemap_) << " " << sizeof(typemap_[0]);
    return 0;
}

运行良好并输出 sizeof: 32 16

单个元素的同时 sizeof 是合法的,因为即使不知道其实际大小,编译器也知道数组由什么组成。

首先创建一个可重现的示例:

static char c[];

char c[8] = "";

int main()
{
    return sizeof c;
}

好吧,这甚至无法编译,因为我们无法声明 c 静态且不完整:

49668931.cpp:1:13: error: storage size of ‘c’ isn’t known
 static char c[];
             ^

将其更改为 extern 就可以了:

extern char c[];

char c[8] = "";

int main()
{
    return sizeof c;
}

但是,如果我们在完成之前需要 c 的大小,那么当然会失败:

extern char c[];

int main()
{
    return sizeof c;
}

char c[8] = "";
49668931.cpp:5:19: error: invalid application of ‘sizeof’ to incomplete type ‘char []’
     return sizeof c;
                   ^

未知边界数组是incompletely-defined对象类型;它的大小和布局是未知的。 typemap_ 的声明只声明了一个未知边界的数组,没有定义我们无法获取它的大小所以 sizeof(typemap_); 失败。

[basic.types]/5,

an array of unknown bound or of incomplete element type, is an incompletely-defined object type. 42

42) The size and layout of an instance of an incompletely-defined object type is unknown.

[basic.types]/6,

The declared type of an array object might be an array of unknown bound and therefore be incomplete at one point in a translation unit and complete later on; the array types at those two points (“array of unknown bound of T” and “array of N T”) are different types.

我会在声明中放入静态数组的元素数。如果稍后我更改实现文件中的数字,编译器将通过某种类型不匹配诊断通知。

也可以return静态函数中的大小,但定义必须与数组初始化驻留在同一个模块中;因此该函数可能是内联的,但绝不会是 constexpr。