Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用构造结构{a[0]}测试;_C_Linux Kernel - Fatal编程技术网

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

C 使用构造结构{a[0]}测试;,c,linux-kernel,C,Linux Kernel,我猜不出诸如 struct { uint64_t offsets[0]; } table; 请给我一些提示。您已经定义了未命名的结构实际上表不是结构名称 所以,如果你有这个声明 typedef struct { uint64_t offsets[0]; } table; 或者 然后,这被称为可变长度数组(称为struct hack) 有一个限制,它应该是结构的最后一个成员 有关它的详细信息您已经定义了未命名的结构实际上表不是一个结构名称 所以,如果你有这个声明 typ

我猜不出诸如

struct 
{
    uint64_t offsets[0];
} table; 

请给我一些提示。

您已经定义了未命名的
结构
实际上
不是
结构
名称

所以,如果你有这个声明

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

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

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


有关它的详细信息

您已经定义了未命名的
结构
实际上
不是一个
结构
名称

所以,如果你有这个声明

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

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

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


关于它的更多信息,您发布的代码正式无效。形式上,C语言不支持大小为
0
的数组

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

因此,即使它进行编译,最终也会得到一个变量
table
,其中不包含任何可用数据。此变量的唯一用途(如果使用静态存储持续时间声明)是通过
&table
表达式(一个“指向匿名结构的指针”类型的指针)生成一个唯一的地址常量

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

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

但是,“结构黑客”的“人工生成”结构声明通常会在灵活数组声明之前包含其他数据字段(没有这些字段,选择“结构黑客”而不是普通数组就没有意义)

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

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

因此,即使它进行编译,最终也会得到一个变量
table
,其中不包含任何可用数据。此变量的唯一用途(如果使用静态存储持续时间声明)是通过
&table
表达式(一个“指向匿名结构的指针”类型的指针)生成一个唯一的地址常量

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

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

但是,“结构黑客”的“人工生成”结构声明通常会在灵活数组声明之前包含其他数据字段(没有这些字段,选择“结构黑客”而不是普通数组就没有意义)

这是一个技巧,可以将任意大小的内存块强制转换为指针类型,并使最后一个数组成员成为可变长度数组。虽然可能不是标准的,但这是可行的,因为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。

这是一个技巧,它允许您将任意大小的内存块强制转换为指针类型,并将最后一个数组成员设置为可变长度数组。虽然可能不是标准的,但这是可行的,因为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 hack”,但您提供的声明不能用于此目的。不同之处在于
uint64\u t offset
将引入类型为
uint64\u t
的字段。同时,大小为
0
(如果在编译器中编译)的数组根本不引入任何数据。您的变量
为空。它本身有大小
0
,这就是为什么我说它没有实际用途。实际上,它唯一的用途就是在内存中占用一些唯一的地址除了一些非常特定于实现的东西外,您现在拥有的东西没有任何实际用途。它类似于经典的“struct hack”,但您提供的声明不能用于此目的。不同之处在于
uint64\u t offset
将引入类型为
uint64\u t
的字段。与此同时,阿拉