使用构造struct {a [0]}测试;

时间:2012-12-25 06:44:35

标签: c linux-kernel

我无法猜测

等构造的用法
struct 
{
    uint64_t offsets[0];
} table; 

请给我一些暗示。

3 个答案:

答案 0 :(得分:5)

您发布的代码正式无效。正式C语言不支持大小为0的数组。

某些编译器(具有松散/遗留错误检查)允许在结构的末尾使用大小为零的数组,有时用于实现所谓的"struct hack"。 (更好的方法是使用大小为1的尾随数组。)但是,您的声明不提供该用法。 “struct hack”需要一个命名的struct类型,并且必须动态分配实际的对象。在您的情况下,结构类型未命名,变量table是非动态定义的。因此,假设您正确地复制了代码,“struct hack”在这里是不可能的。

所以,即使它编译,你最终得到的变量table也没有可用的数据。此变量的唯一用途(如果使用静态存储持续时间声明)是通过&table表达式(“指向匿名结构的指针”类型的指针)生成唯一的地址常量。

将您的声明转换为更接近“struct hack”的方法的一种方法是在其前面添加typedef

typedef struct 
{
  uint64_t offsets[0];
} table; 

然而,“struct hack”的“人工生成”结构声明通常会在灵活数组声明之前包含其他数据字段(没有它们,在普通数组中选择“struct hack”根本就没有意义)。

答案 1 :(得分:1)

这是一个技巧,允许您将任何大小的内存块转换为指针类型,并使最后一个数组成员成为可变长度数组。虽然可能不是标准的,但这可行,因为C数组未经过边界检查。

这是一个非常简单的例子:

typedef struct Foo
{
    int count;
    int array[0];
} Foo;

Foo* foo = (Foo*)malloc(sizeof(Foo) + 5 * sizeof(int));
foo->count = 5;

然后,您可以使用count字段来了解Foo*中有效元素的数量。因为,如上所述,C数组未经过边界检查,当您尝试读取或写入时,编译器和运行时都不会捕获foo->array的大小为0。

答案 2 :(得分:0)

您已定义未命名的struct实际上table是对象而不是struct名称。

所以,如果你有这个声明

typedef struct 
{
    uint64_t offsets[0];
} table; 

或者,

   struct table
    {
        uint64_t offsets[0];
    } table; 

然后,这称为可变长度数组(称为 struct hack )。

有限制,它应该是结构的最后一个成员。

了解更多信息see this article on struct hack