用一个pointer柔性阵列成员 (FAM)将一个定义为一个不“复制”这个FAM?
根据这个程序,这似乎是一种行为,它创建带有FAM的结构的实例,然后检查指向结构的指针和结构的取消引用的“二进制布局”。
#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成员来尊重(指向)结构的士气,因为我们只得到结构的“头”,而不是完整的数组数据?
发布于 2021-07-09 13:47:35
那就对了。编译器不知道数组的大小,并假设这类操作为0,包括复制、返回、赋值和比较。实际上,柔性数组是在结构之后的。
GCC的原型语法更为明显。他们把它写成uint32_t data[0];
发布于 2021-07-09 13:46:43
有点技术性-取消指针在这里是一个错误的名称。实际问题是如何使用FAM复制结构。
您的观察是正确的,如果您试图复制一个结构与FMA,FMA部分将不会被复制。原因很简单--因为编译器不知道分配的存储空间的大小,所以它不能复制FMA的“尾”。
发布于 2021-07-09 14:16:14
C 2018 6.7.2.1 18说:
…在大多数情况下,…忽略了灵活的数组成员。
在使用结构时,C标准中没有提到使用灵活数组成员(是值的一部分),就像在array_t x = *_x;中一样。因此,在这个初始化过程中,数组成员没有被复制,这是因为标准中没有说它是复制的。
该标准还提到了关于灵活数组成员的两件值得注意的事情。下一句允许填充满足灵活数组成员的对齐要求:
特别是
,结构的大小就好像省略了灵活的数组成员,只是它可能有比省略所暗示的更多的后继填充。
后面的句子说,访问该成员(就像对x->data一样)的行为就好像那里确实有一个数组一样,只要为它提供的内存允许那么大。
因此,最后一句允许您手动访问灵活数组成员中的数据,但第一句不要求编译器自动对它们执行任何操作。
这样做的原因当然是编译器通常无法知道灵活数组成员的大小。其他答案(到目前为止)不正确地说明了这一点;他们说编译器不知道的大小。在所示的代码中,编译器当然可以看到大小,因此它缺乏知识并不是不复制灵活数组成员的原因。更准确地说,原因是编译器无法知道在使用结构的所有情况下的大小,因为内存预留可能看不到当前正在编译的代码,因此一般规则是,即使内存预留是可见的,灵活的数组成员也不被视为基本结构的一部分。
https://stackoverflow.com/questions/68317822
复制相似问题