首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用灵活的数组成员定义指向结构的指针不“复制”FAM吗?

使用灵活的数组成员定义指向结构的指针不“复制”FAM吗?
EN

Stack Overflow用户
提问于 2021-07-09 13:41:21
回答 3查看 95关注 0票数 2

用一个pointer柔性阵列成员 (FAM)将一个定义为一个不“复制”这个FAM?

根据这个程序,这似乎是一种行为,它创建带有FAM的结构的实例,然后检查指向结构的指针和结构的取消引用的“二进制布局”。

代码语言:javascript
复制
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int main(){

typedef struct{
  uint8_t  idim;
  uint32_t data[];
}array_t;  // https://gustedt.wordpress.com/2011/03/14/flexible-array-member/

  int64_t  x_bdim = sizeof(array_t) + sizeof(uint32_t)*0x2;
  array_t* _x     = aligned_alloc(0x1000,x_bdim);
  array_t   x     = *_x;
  uint8_t* raw;

  x.idim          = 0xff;
  x.data[0x0]     = 0x11111111;
  x.data[0x1]     = 0x22222222;

  _x->idim          = 0xff;
  _x->data[0x0]     = 0x11111111;
  _x->data[0x1]     = 0x22222222;

  printf("%'ld %'ld %'ld\n", sizeof(array_t), sizeof(array_t) + sizeof(uint32_t)*0x2, x_bdim);

  putchar(0x0a);
  raw = (uint8_t*)_x;
  for(int i=0; i<x_bdim; ++i)
    printf("%02x\n", raw[i]);

  putchar(0x0a);
  for(int i=0; i<0x2; ++i)
    printf("%08x\n", _x->data[i]);

  putchar(0x0a);
  raw = (uint8_t*)&x;
  for(int i=0; i<x_bdim; ++i)
    printf("%02x\n", raw[i]);

  putchar(0x0a);
  for(int i=0; i<0x2; ++i)
    printf("%08x\n", x.data[i]);
}

我是不是漏掉了什么,还是这是对的?我们不应该使用灵活的Array成员来尊重(指向)结构的士气,因为我们只得到结构的“头”,而不是完整的数组数据?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-07-09 13:47:35

那就对了。编译器不知道数组的大小,并假设这类操作为0,包括复制、返回、赋值和比较。实际上,柔性数组是在结构之后的。

GCC的原型语法更为明显。他们把它写成uint32_t data[0];

票数 2
EN

Stack Overflow用户

发布于 2021-07-09 13:46:43

有点技术性-取消指针在这里是一个错误的名称。实际问题是如何使用FAM复制结构。

您的观察是正确的,如果您试图复制一个结构与FMA,FMA部分将不会被复制。原因很简单--因为编译器不知道分配的存储空间的大小,所以它不能复制FMA的“尾”。

票数 2
EN

Stack Overflow用户

发布于 2021-07-09 14:16:14

C 2018 6.7.2.1 18说:

…在大多数情况下,…忽略了灵活的数组成员。

在使用结构时,C标准中没有提到使用灵活数组成员(是值的一部分),就像在array_t x = *_x;中一样。因此,在这个初始化过程中,数组成员没有被复制,这是因为标准中没有说它是复制的。

该标准还提到了关于灵活数组成员的两件值得注意的事情。下一句允许填充满足灵活数组成员的对齐要求:

特别是

,结构的大小就好像省略了灵活的数组成员,只是它可能有比省略所暗示的更多的后继填充。

后面的句子说,访问该成员(就像对x->data一样)的行为就好像那里确实有一个数组一样,只要为它提供的内存允许那么大。

因此,最后一句允许您手动访问灵活数组成员中的数据,但第一句不要求编译器自动对它们执行任何操作。

这样做的原因当然是编译器通常无法知道灵活数组成员的大小。其他答案(到目前为止)不正确地说明了这一点;他们说编译器不知道的大小。在所示的代码中,编译器当然可以看到大小,因此它缺乏知识并不是不复制灵活数组成员的原因。更准确地说,原因是编译器无法知道在使用结构的所有情况下的大小,因为内存预留可能看不到当前正在编译的代码,因此一般规则是,即使内存预留是可见的,灵活的数组成员也不被视为基本结构的一部分。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68317822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档