【问题标题】:Issues with union and memory aligment联合和内存对齐问题
【发布时间】:2014-12-03 17:41:50
【问题描述】:

我目前正在开发一个嵌入式代码端口(在飞思卡尔 S12 上),所以 GNU 和我遇到了工会问题。 我有以下工会

typedef signed short        sint16;
typedef signed long         sint32;

typedef union
{
    sint32 Akku;
    sint16 AkkuHigh;
    sint16 AkkuLow;
} akku_type;

我想访问联合的最高 2 个字节。问题是,AkkuHigh 和 AkkuLow 的起始地址都与 Akku 相同。它似乎是特定于编译器的。我的问题是: 是否存在改变联合行为的编译器标志? 属性((align (2))) 可以帮助我吗?

提前谢谢你

【问题讨论】:

  • highlow 字段打包到一个内部匿名struct 中。严格来说它不是便携式的,但它应该可以工作。
  • 你为什么期望他们有不同的地址?
  • @ParkYoung-Bae:C 允许它,它是一个常见的 C++ 扩展。想知道为什么委员会没有屈服并使其合法化......
  • @ParkYoung-Bae:在结构的开始处填充?你从哪里得到那个打破标准的编译器? (并且在成员 之后不必要的填充只是很奇怪,而且还没有在野外发现。)

标签: c++ c memory unions


【解决方案1】:

是的,AkkuAkkuHighAkkuLow 都具有相同的地址。这就是unions 在 C 中的工作方式。从外观上看,您打算使用一个 32 位成员和一个由两个 16 位成员组成的结构的成员来创建联合。你写的不是实现它的方法。试试吧:

typedef union
{
    sint32 Akku;
    struct s {
      sint16 AkkuHigh;
      sint16 AkkuLow;
    } representation;
} akku_type;

【讨论】:

  • 是否保证AkkuHigh 为高字节,AkkuLow 为低字节?编译器不能决定切换它们吗?
  • @Unapiedra 保证结构成员的地址是有序的。这些地址对应的是实现相关的(通常,这取决于目标架构的字节序。所写的结构适用于大多数大字节序架构)。
  • @Unapiedra:不允许切换它们,但在struct-members 之后添加任意(实现定义的)填充量是(not 在它们之前)。
【解决方案2】:

联合的正确定义见this answer

atribute(align(2)) 如果您在 32 位或 64 位架构上编译它,肯定会对您有所帮助。此外,在 64 位上,sizeof(sint32)8(64 位)。

根据架构的字节序,您可能需要交换 AkkuHighAkkuLow

【讨论】:

  • 只要提到它是有效的 C 但不是 C++,虽然是 C++ 中的一个常见扩展。
  • 究竟什么是无效的 C++?未命名的结构?
  • 是的。匿名类型的未命名成员。当你更正它时 Ping 我。
  • 知道了。完全删除了联合的定义,在另一个答案中描述得很好。
  • 我会保留它并添加免责声明。考虑到该扩展的普遍性,它是 C 中更好的解决方案,并且可以说在 C++ 中也是如此。
猜你喜欢
  • 1970-01-01
  • 2011-05-25
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-05
相关资源
最近更新 更多