【问题标题】:Besides saving space, any other particular advantages of using unions?除了节省空间,使用联合还有什么其他特别的好处?
【发布时间】:2016-10-24 03:51:38
【问题描述】:

在嵌入式编程中,有时会在一个联合中放置多达 15 个结构。这是一种常见的做法,包括我在内的大多数人都认为这是为了节省空间,因为 RAM 太小而且太珍贵。但现在我想知道,还有其他考虑吗?比如速度?

请指教告知。

这里有一个例子供你思考:

typedef struct
{
 union
 { 
  struct{
    ...
  } stru1;


  struct{
    ...
  } stru2;


  struct{
    ...
  } stru3;


  struct{
    ...
  } stru4;

 }
}main_packet

【问题讨论】:

  • 您认为它如何节省空间?这是由于规范中定义的完全不同的原因,很可能是任何解释 C 的教程或书籍。
  • 一个union 占用它最大的项目的大小,所以相反:你浪费了很多空间......

标签: c embedded


【解决方案1】:

使用联合来“节省空间”,即使用它来创建变体,通常被认为是不好的做法(例如被 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 中列出的严格别名的例外情况,这是明确定义的行为:

  • 在其成员中包含上述类型之一的聚合或联合类型(递归地,包括 子聚合或包含联合)

【讨论】:

  • 抱歉打扰了。你的最后一个例子取决于字节顺序,不是吗?我的意思是u16 可以是0
  • @LPs 是的。因此,通常最好通过移位访问整数类型的某些部分。但我可以想象,当您想要以 u16 块读取 u32 时,会有真实的场景。例如,我记得写过一个 eeprom 驱动程序,你只能编程 16 位。
  • 是的,我做了很多次,使用uint16_t u16[sizeof(uint32_t)/sizeof(uint16_t)];
【解决方案2】:

动态内存分配(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 if 构造使用“派生类型”标识符字段(在此案例)。

也可以使用联合来代替指针转换来将原始字节解释为不同的类型:

typedef union
  {
    float fp;
    struct
      {
        unsigned fraction : 23;
        unsigned exponent : 8;
        unsigned sign     : 1;
      }
    fld;
  }
Floating_point;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-27
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多