[英]Dynamically allocate structure and array in it in C
struct Register
with each register having a dynamically allocated array of struct Field
? struct Register
数组,而每个寄存器都有一个动态分配的struct Field
数组? Register_A.FieldArray[23].High
?)? Register_A.FieldArray[23].High
吗?)? How will I initialize register structure efficiently(assuming that register struct array is a big one) ? 我将如何有效地初始化寄存器结构(假设寄存器结构数组很大)? (Like a data segment without spending any compute)
(就像一个数据段,而无需花费任何计算)
struct Field { char High; char Low; char Attribute; }; struct Register { unsigned int ResetValue; struct Field FieldArray[]; };
I strongly discourage you from using a flex array, because they're nothing but a kludge. 我强烈不鼓励您使用flex数组,因为它们不过是一种麻烦。 You should instead declare and use it as a
struct Field *
, malloc
ing it to size like any other dynamic array. 而应该声明,并把它作为一个
struct Field *
, malloc
是荷兰国际集团,以规模像任何其他动态数组。
That said, to malloc
with an array size of n_elem
: 这就是说,对
malloc
与阵列大小n_elem
:
struct Register register = malloc(sizeof(*register) + n_elem * sizeof(*register->FieldArray));
To access the elements: 要访问元素:
char high = register->FieldArray[0].High;
For initialization: in gcc, at least, you can initialize the array part statically like any other static array. 对于初始化: 至少在gcc中,您可以像其他任何静态数组一样对数组部分进行静态初始化。 I'm not sure how other compilers handle it.
我不确定其他编译器如何处理它。
Why flex arrays are discouraged: 为什么不鼓励使用弹性数组:
I'll link this post , but I don't think the answer is complete (most of the discouragement is because it's c-99 only), so I'll add my thoughts. 我将链接此帖子 ,但我认为答案并不完整(大多数不鼓励是因为它仅适用于c-99),所以我将添加我的想法。
They are an exception. 他们是一个例外。 In essence, you're declaring the array to be of zero size and accessing it out of bounds every time, just to an extent you have allocated for.
本质上,您是在声明数组的大小为零,并且每次都超出您所分配的范围而对其进行访问。 You can't use a struct with a flexible array just like any other struct, eg you can't take the
sizeof
the flexible array. 您不能像其他任何结构一样将结构与弹性数组一起使用,例如,您不能采用弹性数组的
sizeof
。 If you declare a static one or an array of them, you can't use the array member because there's no space allocated for it. 如果声明一个静态数组或它们的一个数组,则不能使用该数组成员,因为没有为其分配空间。
Example of using them in an array: 在数组中使用它们的示例:
#include <stdio.h>
struct test {
int val;
int arr[];
};
int main() {
struct test tarr[2];
printf("%p\n%p\n", &tarr[0].arr[0], &tarr[1].val);
}
Output: 输出:
0x7fff59b67164
0x7fff59b67164
They are at the same address. 他们在同一个地址。 If you try to write to the array member, you overwrite the next object.
如果尝试写入数组成员,则将覆盖下一个对象。 If you try to read from it, you read data from the next object.
如果尝试从中读取数据,则会从下一个对象读取数据。 Depending on padding, this could even be a nonsense value from the padding.
根据填充,这甚至可能是来自填充的废话值。
They're like goto
statements, both are potentially useful but more often a bad idea. 它们就像
goto
语句,两者都可能有用,但通常是一个坏主意。 If you don't know why they're dangerous, you shouldn't be using them (in real code; it's not a bad idea to play around with them in a test program to see how to use them correctly and how they can introduce problems). 如果您不知道为什么它们很危险,就不应该使用它们(在真实代码中;在测试程序中使用它们以了解如何正确使用它们以及如何引入它们不是坏主意。问题)。
A way to do it is by changing the size of the struct Register
: 一种方法是通过更改
struct Register
的大小:
struct Register
{
unsigned int ResetValue;
struct Field FieldArray[1];
};
struct Register *Register_Create()
{
struct Register *reg = calloc(1, sizeof(struct Register) - sizeof(struct Field));
// check for NULL pointer
return reg;
}
struct Register *Register_SetSize(struct Register *reg, size_t size)
{
// check for NULL
reg = realloc(reg, sizeof(struct Register) + sizeof(struct Field) * (size - 1));
// check for NULL
return reg;
}
Here's an example on how to use this: 这是有关如何使用此示例:
struct Register *reg = Register_Create();
reg = Register_SetSize(register, 5);
// You now have space for 5 elements in reg->FieldArray
reg->FieldArray[3].High = 'B';
Keep in mind that this solution only works if FieldArray
is placed at the end of the struct
. 请记住,只有将
FieldArray
放在struct
的末尾,此解决方案才有效。
You are going to have to know how big the FieldArray is. 您将必须知道FieldArray有多大。 If it isn't fixed, you need to declare with max value.
如果它不是固定的,则需要使用最大值声明。 Then you can just alloc a Register and access as you specified
然后,您可以按照您的指定分配一个注册并访问
Flexible array members are a part of C99. 柔性阵列成员是C99的一部分。
struc
with flexible array member just as you think you should: malloc(sizeof(struct Register) + sizeof(struct Field[n]))
, where n
is the size you want. struc
: malloc(sizeof(struct Register) + sizeof(struct Field[n]))
,其中n
是您想要的大小。 Don't forget to initialize the array and to keep track of n
, best by dedicating a member to that purpose n
,最好是通过为此目的指定一个成员 BTW: the malloc
above may be wasting some bytes due to padding, but usually it is not worth thinking about the exact formula. 顺便说一句:上面的
malloc
可能由于填充而浪费了一些字节,但是通常不值得考虑确切的公式。 The minimal one has a max and uses offsetof
. 最小的有一个最大值,并使用
offsetof
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.