我猜不出结构的使用,例如
struct
{
uint64_t offsets[0];
} table;
请给我一些提示。
您发布的代码正式无效。形式上 C 语言不支持 size 的数组0
。
一些编译器(带有松散/遗留错误检查)允许在结构末尾放置一个大小为零的数组,这有时用于实现所谓的“struct hack”。(更好的方法是使用大小为 1 的尾随数组。)但是,您的声明并未提供该用途。“结构破解”需要命名结构类型,并且必须动态分配实际对象。在您的情况下,结构类型未命名,并且变量table
是非动态定义的。因此,假设您正确复制了代码,“struct hack”在这里是没有问题的。
因此,即使它编译,您最终也会得到table
不包含可用数据的变量。这个变量的唯一用途(如果用静态存储持续时间声明)是通过&table
表达式(“指向匿名结构的指针”类型的指针)产生一个唯一的地址常量。
将您的声明变成更接近“struct hack”的一种方法是typedef
在它前面添加一个
typedef struct
{
uint64_t offsets[0];
} table;
但是,“struct hack”的“人工生成”结构声明通常会在灵活数组声明之前包含其他数据字段(没有它们,在普通数组上选择“struct hack”根本没有意义)。
这是一个技巧,可让您将任意大小的内存块转换为指针类型,并使最后一个数组成员成为可变长度数组。虽然可能不是标准的,但这是可行的,因为 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 的数组。
您定义的未命名struct
实际上table
是对象而不是struct
名称。
所以,如果你有这个声明
typedef struct
{
uint64_t offsets[0];
} table;
或者,
struct table
{
uint64_t offsets[0];
} table;
然后,这称为变长数组(称为struct hack)。
有一个限制,它应该是结构的最后一个成员。
有关它的更多信息,请参阅这篇关于 struct hack 的文章