在嵌入式编程中,通常有时会在一个联合中放置多达15个结构。这是一种常见的做法,包括我在内的大多数人都认为节省空间是因为RAM太小而且太珍贵。但现在我想知道,还有其他考虑因素吗?例如,速度?
请启发并告知。
这是你想法的一个例子:
typedef struct
{
union
{
struct{
...
} stru1;
struct{
...
} stru2;
struct{
...
} stru3;
struct{
...
} stru4;
}
}main_packet
答案 0 :(得分:4)
使用联合来“节省空间”,即使用它来创建变体,通常被认为是不好的做法(例如被MISRA-C禁止),我建议不做任何事情。变体类型的存在几乎总是程序设计糟糕的表现。
联合的最常见目的是将它们用于类型双关语,这意味着您可以写入一个联盟成员,然后通过另一个成员读取该数据。这是C中明确定义的行为,在进行与硬件相关的编程时非常有用。
例如,您可以执行以下操作:
typedef union
{
uint32_t u32;
uint8_t u8 [4];
} my32_t;
my32_t my32;
my32.u32 = 1;
if(my32.u8[0] == 1)
{
puts("little endian");
}
else
{
puts("big endian");
}
工会也可用于躲避the strict aliasing rules。像这样的代码会调用未定义的行为:
uint32_t u32 = 1;
uint16_t u16 = *(uint16_t*)&u32; // bad, strict aliasing violation
为避免此错误,可以将代码重写为:
typedef union
{
uint32_t u32;
uint16_t u16;
} something_t;
something_t x;
x.u32 = 1;
uint16_t u16 = x.u16;
根据6.5 / 7中列出的严格别名的例外情况,这是明确定义的行为:
- 一种聚合或联合类型,包括其成员中的上述类型之一(包括递归地,一个成员) subaggregate或contains union)
答案 1 :(得分:0)
动态内存分配(malloc / free)是节省空间的一般方法,通过将内存重用于生命周期不重叠的数据结构。工会是一种非常不灵活,难以维护的方法。它们只应用于malloc / free的时间开销真正不可接受的特殊情况。
工会也被用来提供"原始"如果你用C ++编码,那将是一个类层次结构的野兽。而不是:
class A { ... };
class B : public A { ... };
class C : public A { ... };
class D : public A { ... };
你写道:
struct H
{
struct A a;
enum { Really_B, Really_C, Really_D } really;
union
{
struct B b;
struct C c;
struct D d;
};
};
在C ++中,您使用虚函数来获取B,C,D所需的不同行为。在C中,您使用较少的可维护开关或if / else如果构造使用"派生类型"标识符字段("真的"在这种情况下)。
也可以使用联合而不是指针转换来将原始字节解释为不同的类型:
typedef union
{
float fp;
struct
{
unsigned fraction : 23;
unsigned exponent : 8;
unsigned sign : 1;
}
fld;
}
Floating_point;