【问题标题】:Is it possible to make a union right aligned in C?是否可以在 C 中使联合右对齐?
【发布时间】:2021-04-11 15:24:45
【问题描述】:

例如,联合的默认对齐方式如下:

union{
   uint32_t v4;
   __uint128_t v6;
}ip;

//in memory
//aaaa
//bbbbbbbbbbbbbbbb

但我想让联合右对齐:

//            aaaa
//bbbbbbbbbbbbbbbb

是否有可能在 C 中实现这一点?

【问题讨论】:

  • 我不确定第一张图是否正确。也许如果你有一个 128 位架构。
  • 你会如何使用这样的联合?
  • @dbush 当你在其中保存一个 ipv4 地址时,你可以使用ip.v6 直接获取一个 v6 地址(前 96 位为 0)。但是有个缺陷是需要提前将前96位补0,否则不知道是ipv6地址还是ipv4地址。

标签: c union memory-alignment


【解决方案1】:

您可以为此使用 C11 匿名结构。

union {
#pragma pack(1)
    struct {
        char padding_[sizeof(__uint128_t) - sizeof(uint32_t)];
        uint32_t v4;
    };
#pragma pack(0)
    __uint128_t v6;
} ip;

// usage
ip.v4 = 0x7F000000;

【讨论】:

  • 我建议添加属性'packed'以确保没有添加隐式填充字节
  • 好主意。我在匿名结构中添加了#pragma pack(1),它也应该适用于 MSVC。
  • 小心“打包”结构。包装不仅去除填充物。它还将告诉编译器该结构可以并且将具有任意对齐方式,这可能会根据平台和代码极大地影响性能。见godbolt.org/z/1q8ascav9
  • @ElderBug 我认为联合应该具有__uint128_t 的对齐方式,因为#pragma pack(1) 适用于匿名结构,而不是整个联合。
  • 如果打包仅用于内部结构,那么可以。为此,您需要在结构后添加#pragma pack(0)
【解决方案2】:

你可以定义

union{
   struct {
     char uselessgap[12];
     uint32_t v4;
   } s;
   __uint128_t v6;
}ip;

然后在你的 C 代码中使用s.v4 而不是v4;你甚至可以

#define v4 s.v4

我不确定这是个好主意(那个宏)。

另一种方法是使用您的GCC plugin(对于GCC 编译器的特定 版本)和一些由它处理的__attribute__

【讨论】:

猜你喜欢
  • 2011-03-07
  • 1970-01-01
  • 2015-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-12
  • 2020-08-08
  • 1970-01-01
相关资源
最近更新 更多