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

时间:2018-04-05 09:34:11

标签: c++ arrays sizeof

我有以下数组:

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_);

给出编译时错误

  

错误C2070'std :: pair []':   非法大小的操作数

即使这个

sizeof(typemap_[0]);

是合法的,数组是固定大小的吗?

类型定义为:

enum class Type {...} 

5 个答案:

答案 0 :(得分:4)

似乎编译器缺少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是合法的,因为即使不知道它的实际大小,编译器也知道数组包含什么。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

未知边界数组是未完全定义的对象类型;它的大小和布局是未知的。 sizeof(typemap_);的声明只声明一个未知界限的数组,没有定义我们无法得到它的大小,因此template<class T, size_t MaxQueueSize> class Queue { std::condition_variable consumer_, producer_; std::mutex mutex_; using unique_lock = std::unique_lock<std::mutex>; std::queue<T> queue_; public: template<class U> void push_back(U&& item) { unique_lock lock(mutex_); while(MaxQueueSize == queue_.size()) producer_.wait(lock); queue_.push(std::forward<U>(item)); consumer_.notify_one(); } T pop_front() { unique_lock lock(mutex_); while(queue_.empty()) consumer_.wait(lock); auto full = MaxQueueSize == queue_.size(); auto item = queue_.front(); queue_.pop(); if(full) producer_.notify_all(); return item; } }; 失败。

[basic.types]/5

  

未知边界或不完整元素类型的数组,是未完全定义的对象类型 42

     

42)未完全定义的对象类型的实例的大小和布局是未知的。

[basic.types]/6

  

数组对象的声明类型可能是未知边界的数组,因此在翻译单元中的某个点处不完整,稍后会完成;这两个点的数组类型(“T的未知边界数组”和“N T数组”)是不同的类型。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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

也可以在静态函数中返回大小,但定义必须与数组初始化位于同一模块中;因此,函数可能是内联的,但从不constexpr。