Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.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 获取结构中零长度数组元素类型的大小_C_Gcc - Fatal编程技术网

C 获取结构中零长度数组元素类型的大小

C 获取结构中零长度数组元素类型的大小,c,gcc,C,Gcc,也许标题让人困惑,但想法很简单。鉴于以下结构: struct z { uint64_t _a; uint64_t _b; struct { char _c[64]; uint64_t _d; } data[0]; } __attribute__((packed)); 如何获得匿名内部结构数据类型的大小?我不想命名结构并使名称空间混乱,但在计算序列化缓冲区的总长度时,我确实需要它的大小,对于非零数据尾部,序列化缓冲区的总长度是什么样

也许标题让人困惑,但想法很简单。鉴于以下结构:

struct z {
    uint64_t _a;
    uint64_t _b;
    struct {
        char _c[64];
        uint64_t _d;
    } data[0];
} __attribute__((packed));
如何获得匿名内部结构数据类型的大小?我不想命名结构并使名称空间混乱,但在计算序列化缓冲区的总长度时,我确实需要它的大小,对于非零
数据
尾部,序列化缓冲区的总长度是什么样子

您会发现类似于:

struct z *p;
sizeof(struct z) == 16
sizeof(*p) == 16
sizeof(p->data) == 0
这些结果是可以预期的。然而,我希望看到的是:

sizeof(typeof(p->data)) == 72
但是,不幸的是,我仍然感到

sizeof(typeof(p->data)) == 0
我认为这可能是因为该结构未命名,但在为其提供名称后,您会发现早期的结果仍然正确

有没有办法获得匿名内部零长度结构的大小

但是,在计算序列化缓冲区的总长度时,我确实需要它的大小,对于非零数据拖车,序列化缓冲区的总长度是什么样子

使用
sizeof()
无法做到这一点。你必须自己记录尺寸

(用粗体表示我的观点,并注意到这一点):

GNUC中允许声明长度为零的数组作为扩展。A. 零长度数组可以用作结构的最后一个元素 这实际上是可变长度对象的标题:

struct line {
  int length;
  char contents[0];
};

struct line *thisline = (struct line *)
  malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
尽管零长度数组的大小为零,但 这种类型可能会由于以下原因而增加封闭类型的大小: 尾垫

请注意示例代码如何跟踪数组中的元素数。

我将使用:

sizeof(p->data[0])

由于它位于
sizeof
内部,因此未进行计算,
p->data[0]
实际上不会取消引用
p->data
。编译器只计算出类型。

只需命名即可。如果不是说

struct {
    char _c[64];
    uint64_t _d;
} data[0];
你说

struct data {
    char _c[64];
    uint64_t _d;
} data[0];

然后
sizeof(struct data)
将告诉您它是sizeof。

请注意,零长度数组元素是一个不可移植的GCC扩展:“如果表达式是常量表达式,它的值应大于零。”您可能应该使用。您必须自己跟踪这样一个数组中的元素数。
sizeof type->p_data[0]
这本身当然是非法的,但可能并不重要。但事实上,您应该使用FAM,因为您似乎无论如何都在使用GCC。@AnttiHaapala很好奇为什么这个表达式是非法的,因为它确实有效。由于
sizeof
是在编译时计算的,因此您并没有严格地访问数组边界以外的数据。
sizeof sizeof p->data[0]
sizeof(typeof(FAM))
不同,前者是数组元素的大小,后者是数组的大小。为什么期望这两个提供相同的结果?是的。像
sizeof
这样的运算符不会将数组转换为指向数组初始元素“per”的“指针…”,除非它是sizeof运算符的操作数,或者是一元&运算符,或者是用于初始化数组的字符串文字,具有“array of type”类型的表达式转换为具有类型的表达式指向数组对象“C17dr§6.3.2.2 3.
sizeof(数组)”初始元素的“类型指针”
是数组大小,而不是元素大小。一般来说,我没有遇到过这个问题,因为我通常会将FAM指定为
char
uint8_t
类型。但我遇到的情况是,尾随数据有点复杂,因此我打算使用如上所示的FAM结构。虽然它确实有效,但我遇到了关于获取类型编译时大小的问题。我确实理解它的元素大小显然为零。我不确定为什么这么难做到,或者显然需要非法表达式,如
sizeof(p->data[0])
来实现(这是可行的)。谢谢你的回答,但我想你没有抓住我问题的重点。我上面的结构与你的不一样。我知道
内容
是指一些
长度
大小的数据块的开头。我明白了。我希望我的
内容
-类似元素的结构能多一点,以防止类似的丑陋第二位代码。@sherrellbc不幸的是,你不能,就像你不能通过在
malloc()返回的指针上使用
sizeof()
获得分配给
malloc()的
int
数组的大小一样
。我的答案是提供一个实际的引用,说明在用作结构末尾较大数组的占位符/引用的零长度数组上不能使用
sizeof()
。这种编码模式之所以命名为“struct hack”.GCC的零长度数组和标准C灵活数组成员是将黑客推入标准化代码的有用尝试。@sherrellbc如果是
char
uint8\t
类型的数组,如何获得长度?我得到
sizeof(contents)
在本例中是零,也应该是零。我不明白的是为什么像
sizeof(typeof(contents))
这样的东西在这里不等于
sizeof(char)
。这就是为什么我希望
sizeof(typeof(p->data))
将给出灵活数组成员类型的大小。但它也只返回零,尽管它有一个真正的非零类型。但可能真正的答案只是“FAM不适用于非char/uint8_t-typed元素”。这是正确的答案。它以定义良好的方式获取匿名结构的大小。