零长度的阵列零长度的阵列(Array of zero length)

2019-05-10 11:51发布

我正在重构了一些旧代码,并发现含零门长度阵列(下图)几个结构。 警告由编译郁闷,当然,但我失败了含有这种结构(错误2233)“新”结构打造。 阵“byData”作为指针,但为什么不改用指针? 或长度为1的数组? ,当然,不添加评论让我享受这个过程...任何原因,使用这样的事情? 在重构这些有什么建议?

struct someData
{
   int nData;
   BYTE byData[0];
}

NB这是C ++,Windows XP中,VS 2003

Answer 1:

是的,这是C-哈克。
创建任何长度的数组:

struct someData* mallocSomeData(int size)
{
    struct someData*  result = (struct someData*)malloc(sizeof(struct someData) + size * sizeof(BYTE));
    if (result)
    {    result->nData = size;
    }
    return result;
}

现在你有someData的目的具有指定长度的数组。



Answer 2:

还有,不幸的是,有几个原因,你会在结构末端声明零长度的数组。 它本质上使您能够有一个从API返回的可变长度结构的能力。

雷蒙德陈做了关于这个问题的一个很好的博客文章。 我建议你看看这篇文章,因为它有可能包含你想要的答案。

注意,在他的岗位,它与大小为1,而不是0 就是这种情况,因为零个长度数组是一个较新的进入标准的阵列交易 他的文章还是应该适用于您的问题。

http://blogs.msdn.com/oldnewthing/archive/2004/08/26/220873.aspx

编辑

注意:虽然雷蒙德的帖子中写道:0长度数组在C99是合法的,他们实际上还没有在法律C99。 取而代之的是0长度的数组在这里你应该用一个长度为1阵列



Answer 3:

这是一个旧的C黑客允许灵活大小的数组。

在C99标准,因为它支持的ARR []语法这时并不需要。



Answer 4:

您对“为什么不使用大小为1的数组” intution是即期。

该代码是做“C结构黑客”错误的,因为零个长度数组的声明是违反约束。 这意味着编译器可以拒绝你的黑客马上在编译时蝙蝠与停止翻译的诊断信息。

如果我们想要犯下一个黑客,我们必须潜入它过去的编译器。

做了“C结构破解”以正确的方式(这是一个用C方言追溯到1989 ANSI C,而且可能更早兼容)是用大小为1的完全有效的数组:

struct someData
{
   int nData;
   unsigned char byData[1];
}

此外,代替sizeof struct someData ,之前的部分的尺寸byData使用计算:

offsetof(struct someData, byData);

要分配struct someData与42个字节的空间byData ,我们会再使用:

struct someData *psd = (struct someData *) malloc(offsetof(struct someData, byData) + 42);

请注意,此offsetof计算实际上是正确的计算,即使在阵列大小为零的情况下。 你看, sizeof整体结构可以包括填充。 举例来说,如果我们有这样的事情:

struct hack {
  unsigned long ul;
  char c;
  char foo[0]; /* assuming our compiler accepts this nonsense */
};

大小struct hack是因为对定位很可能衬垫ul成员。 如果unsigned long为四个字节宽,则很可能sizeof (struct hack)是8,而offsetof(struct hack, foo)几乎肯定5. offsetof方法是获得该结构的前部的尺寸准确的方式只是前阵。

因此,这将是重构代码的方式:使其符合经典的,高度可移植的结构黑客。

为什么不使用指针? 由于指针占用额外的空间,必须进行初始化。

还有其他一些很好的理由不使用指针,即指针需要一个地址空间才能有意义。 该结构黑客是externalizeable:也就是说,有在这样的布局符合外部存储情况,如文件,包或共享内存,在你不想指针,因为他们是没有意义的领域。

几年前,我曾经在传递内核和用户空间之间的界面共享内存消息结构黑客。 我不想指针那里,因为他们本来有意义的,只是在过程中产生的消息的原始地址空间。 该软件的核心部分在不同的地址必须着眼于利用自身的映射内存,所以一切都基于偏移计算。



Answer 5:

值得指出的IMO做大小计算,这是雷蒙德陈文章上面链接中使用的最佳方法。

struct foo
{
    size_t count;
    int data[1];
}

size_t foo_size_from_count(size_t count)
{
    return offsetof(foo, data[count]);
}

的第一个条目关期望的分配的端部的偏移,也是所希望的分配的大小。 国际海事组织是做大小计算的一个非常优雅的方式。 没关系可变大小的数组的元素类型是什么。 该offsetof(或FIELD_OFFSET或UFIELD_OFFSET在Windows)总是写相同的方式。 没有的sizeof()的表达式意外陷入困境。



文章来源: Array of zero length