5

我正在编写一个结构来描述我需要的常量值,并注意到一些奇怪的东西。

namespace res{
    namespace font{
        struct Structure{
            struct Glyph{
                int x, y, width, height, easement, advance;
            };
            int glyphCount;
            unsigned char asciiMap[];   // <-- always generates an error
            Glyph glyphData[];          // <-- never generates an error
        };
        const Structure system = {95, 
                              {
                                 // mapping data
                              }, 
                              {
                                 // glyph spacing data
                              }
        }; // system constructor
    } // namespace font
} // namespace res

的最后两个成员Structure,即未调整大小的数组,如果它们本身不停止编译器。但是如果它们包含在结构的定义中,则会导致错误,说“类型不完整”

如果我给第一个数组一个大小,这不再是一个问题。在这种情况下这不是问题,但我仍然很好奇......

我的问题是,为什么我的结构中可以有一个大小不一的数组,但有两个会导致问题?

4

5 回答 5

5

在标准 C++ 中,您根本不能这样做,尽管一些编译器支持它作为扩展。

在 C 中, a 的每个成员都struct需要在struct. 这意味着最后一个成员的大小可能未知;但它之后什么都不会发生,所以没有办法拥有超过一个大小未知的成员。

如果您确实在 C++ 中利用了您的编译器对这种 hack 的非标准支持,那么请注意,如果其中的任何成员struct不重要,事情可能会出现可怕的错误。一个对象只能通过分配一块原始内存并将其重新解释为这种类型来“创建”最后一个非空数组;如果你这样做,将不会调用任何构造函数或析构函数。

于 2012-12-20T11:51:29.737 回答
3

您正在使用非标准的 microsoft 扩展。C11(注意:C,而不是 C++)允许结构中的最后一个数组没有大小(阅读:最多一个数组):

Microsoft 扩展允许 C 或 C++ 结构或类的最后一个成员是可变大小的数组。这些被称为未调整大小的数组。结构末尾的无大小数组允许您附加可变大小的字符串或其他数组,从而避免指针取消引用的运行时执行成本。

// unsized_arrays_in_structures1.cpp
// compile with: /c
struct PERSON {
   unsigned number;
   char name[];   // Unsized array
};

如果对这个结构应用 sizeof 运算符,则认为结束数组大小为 0。这个结构的大小为 2 个字节,即无符号成员的大小。要获取 PERSON 类型变量的真实大小,您需要单独获取数组大小。

结构的大小与数组的大小相加,得到要分配的总大小。分配完毕后,将数组复制到结构体的数组成员中,如下图:

于 2012-12-20T11:46:52.193 回答
2

编译器需要能够决定结构中每个成员的偏移量。这就是为什么您不允许在未调整大小的数组之后放置任何其他成员的原因。由此可见,一个结构中不能有两个未调整大小的数组。

于 2012-12-20T11:48:33.390 回答
1

它是Microsoft 的扩展,并且sizeof(structure) == sizeof(structure_without_variable_size_array).

我猜他们使用初始化程序来查找数组的大小。如果您有两个可变大小的数组,则找不到它(相当于找到一个只有 1 个方程的 2-unknown 系统的唯一解......)

于 2012-12-20T11:48:47.817 回答
1

struct至少在 C++ 中,不允许在 , 句点中使用没有维度的数组。在 C 中,最后一个成员(并且只有最后一个)可以在没有维度的情况下声明,并且某些编译器在 C++ 中允许将此作为​​扩展,但您不应该指望它(在严格模式下,他们至少应该抱怨关于它)。如果最后一个元素的维度为 0(也是扩展,需要在严格模式下进行诊断),则其他编译器已经实现了相同的语义。

将不完整数组类型限制为最后一个元素的原因很简单:任何后续元素的偏移量是多少?即使它是最后一个元素,对结果结构的使用也有限制:例如,它不能是另一个结构或数组的成员,并且 sizeof忽略最后一个元素。

于 2012-12-20T11:58:19.450 回答