C柔性阵列用另一种类型而不是malloc定义
灵活数组的一般用法是使用Malloc来定义柔性阵列。我正在尝试使用另一个结构来探索定义灵活数组。 。
typedef struct {
uint64_t header;
size_t data_size;
float data[];
} test_base_t;
typedef struct {
test_base_t base;
float data[3];
} test_t;
据我了解,需要在结构末尾定义灵活数组 Clangd将发出以下警告。 -wgnu-variable sized-type-not-at-at-at-ind-code>
我只是想问一个人以前是否已经这样做了,这是否安全?还是有一种更好的方法来定义没有异洛克的柔性阵列尺寸?
然后,您可以将对象的用法包裹在宏中,以静态sustert ext.base.data == ext.data
在铸造和传递给常规API之前,请消耗code> test_base_t 。这样,您可以拥有编译所需的内存而不是分配。
编辑
似乎对我想如何消费感到困惑,这是一个示例
#define SUM_BASE(test) \
sum_base(&test->base); \
_Static_assert(test->data == test->base.data);
float sum_base(test_base_t *base)
{
float sum = 0;
for (size_t i = 0; i < base->data_size; i++)
{
sum += base->data[i];
}
return sum;
}
test_t test = { .base = { .data_size = 3, }, .data = { 1, 2, 3, }, };
SUM_BASE((&test));
the general usage of flexible array is to use malloc to define the flexible array. I'm trying to explore defining the flexible array with another struct. An example
typedef struct {
uint64_t header;
size_t data_size;
float data[];
} test_base_t;
typedef struct {
test_base_t base;
float data[3];
} test_t;
As I understand, flexible array needs to be defined at the end of a struct. And clangd will give the following warning. -Wgnu-variable-sized-type-not-at-end
I just wanted to ask if anybody has done this before and is it safe? Or is there a better way to define flexible array size without alloc?
You can then wrap the usage of the object in a macro to static assert ext.base.data == ext.data
before casting and passing to a general API consumes test_base_t
. This way you can have the memory required in compile instead of allocing.
Edit
There seem to be a confusion on how I wanted to consume it, here is an example to demonstrate
#define SUM_BASE(test) \
sum_base(&test->base); \
_Static_assert(test->data == test->base.data);
float sum_base(test_base_t *base)
{
float sum = 0;
for (size_t i = 0; i < base->data_size; i++)
{
sum += base->data[i];
}
return sum;
}
test_t test = { .base = { .data_size = 3, }, .data = { 1, 2, 3, }, };
SUM_BASE((&test));
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您无法使用初始化的数组创建
test_base_t
的实际实例,但是您可以使用指定长度的初始化数组创建复合文字,并以test_base_t
POINTERS的形式施放其地址。鉴于它们具有完全相同的类型,因此两种结构的布局和对齐都应兼容。这是一个示例:
这是另一种方法,也许更接近您的期望,使用
union
与base
具有灵活类型的基本成员,并且具有适当数组的参数实例类型尺寸:You cannot create actual instances of
test_base_t
with an initialized array, but you can create compound literals with an initialized array of a specified length and cast their address astest_base_t
pointers. The layout and alignment of both structures should be compatible, given that they have exactly the same types, save for the flexible array length.Here is an example:
Here is another approach, perhaps closer to your expectations, using a
union
with abase
member with the flexible type and a parametric instance type with the appropriate array size:C 2018 6.7.2.1 3谈到包含灵活数组成员的结构:
因此,
test_t
在问题中输入违反了此“应”要求,C 2018 4 2说,这使得行为未由C标准定义。编译器可以拒绝此代码。如果编译器接受它,则程序的行为未由C标准定义。作为可能出问题的一个示例(因为C标准允许它),请考虑以下代码:
因为
test.base.data [0]
从未通过该表达式分配一个值,并且标准不要将test.data
定义为baliastest.base.data
,编译器可以假设test.base.base.data [0]
>是非初始化的,因此未指定,即使float
类型,此printf
也可以使用任何值,即使test.base.base.base.data [0]
和test.data [0]
名义上参考相同的内存。在此代码中:
编译器可以假设,由于
test.data
从未初始化,因此从test初始化它时,它不需要复制到
。复制
C 2018 6.7.2.1 3 says of a structure containing a flexible array member:
Thus, the
test_t
type in the question violates this “shall” requirement, and C 2018 4 2 says that makes the behavior not defined by the C standard. A compiler could reject this code. If the compiler accepts it, the behavior of the program is not defined by the C standard.As an example of what could go wrong (in that the C standard allows it), consider this code:
Since
test.base.data[0]
was never assigned a value through that expression, and the standard does not definetest.data
to aliastest.base.data
, the compiler may assume the value oftest.base.data[0]
is uninitialized and hence unspecified, and thisprintf
may use any value of thefloat
type, even iftest.base.data[0]
andtest.data[0]
nominally refer to the same memory.And in this code:
The compiler may assume that, since
test.data
was never initialized, it does not need to be copied tocopy
when initializing it fromtest
.