C ++ 11中的可变长度Struct NonStandard?

时间:2012-03-05 20:47:36

标签: c++ c++11

  

可能重复:
  Is the “struct hack” technically undefined behavior?

我检查了C ++ 11中是否允许零长度数组。看起来他们不是。来自8.3.4 Arrays [dcl.array]

  

如果存在常量表达式(5.19),则它应为整数常量表达式,其值应大于零。

因为我不能使用零长度数组是否可以在标准/良好定义时使用可变长度的结构?例如,我想做类似下面的事情。当缓冲区可能空闲时,如何使其定义良好和标准。

-edit-相关:Array of zero length

struct MyStruct {
    uint size;
    int32 buf[0];//<-- NonStandard!
};
...
auto len=GetLength();
auto ptr=GetPtr();
auto bytelen=len*sizeof(int32);
var p = reinterpret_cast<MyStruct*>(malloc(bytelen))
p->size=len
memcpy(p->buf, ptr, bytelen)
return p;

3 个答案:

答案 0 :(得分:7)

这是C ++,而不是C.你不需要在C ++中使用这个灵活的数组成员hack,因为你可以很容易地创建一个模板类,它可以赋予任何结构一个灵活的数组超过结束并封装指针算术计算和内存分配使其工作。观看:

#include <cstring>

template <typename STRUCT, typename TYPE> class flex_struct {
public:
  TYPE *tail()
  {
    return (TYPE *) ((char *) this + padded_size());
  }

  // substitute malloc/free here for new[]/delete[] if you want
  void *operator new(size_t size, size_t tail)
  {
    size_t total = padded_size() + sizeof (TYPE) * tail;
    return new char[total];
  }

  void operator delete(void *mem)
  {
    delete [] (char *) mem;
  }
private:
  static size_t padded_size() {
    size_t padded = sizeof (flex_struct<STRUCT, TYPE>);
    if(padded % alignof(TYPE) != 0) {
         padded = padded & ~(alignof(TYPE)-1) + alignof(TYPE);
    }
    return padded;
  }
};

struct mystruct : public flex_struct<mystruct, char> {
  int regular_member;
};

int main()
{
  mystruct *s = new (100) mystruct; // mystruct with 100 chars extra
  char *ptr = s->tail();            // get pointer to those 100 chars
  memset(ptr, 0, 100);              // fill them
  delete s;                         // blow off struct and 100 chars
}

答案 1 :(得分:6)

不,you cannot do it compliantly *。

使用std::vector

*我假设C ++没有添加任何与此区域中的C相矛盾的规则。 IMO它非常不可能,虽然我没有时间在那一刻验证。

答案 2 :(得分:1)

结构黑客从来都不是标准的。这应该是一个标准的可行替代品:

struct MyStruct {
    uint size;
    int32 buf[1];
};