在C语言中是否有可能使一个联合体(union)右对齐?

4
例如,联合体的默认对齐方式如下:
union{
   uint32_t v4;
   __uint128_t v6;
}ip;

//in memory
//aaaa
//bbbbbbbbbbbbbbbb

但我想将一个联合右对齐:

//            aaaa
//bbbbbbbbbbbbbbbb

在C语言中能否实现这个功能?


我不确定第一张图是否正确。也许如果你有一个128位的架构会更好。 - mkrieger1
你会如何使用这样的联合体? - dbush
@dbush 当你在其中保存一个ipv4地址时,可以使用ip.v6直接获取v6地址(前96位为0)。但是存在一个缺陷,你需要提前用0填充前96位,否则你无法确定它是IPv6地址还是IPv4地址。 - Sam Chiu
2个回答

7
你可以使用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;

5
我建议添加属性“packed”以确保没有隐式的填充字节被添加。 - tstanisl
好主意。我在匿名结构体中添加了#pragma pack(1),这应该也适用于MSVC。 - Ray Hamel
2
小心使用“packed”结构体。打包不仅会删除填充,还会告诉编译器该结构体可以并且将具有任意对齐方式,这可能会根据平台和代码极大地影响性能。请参见https://godbolt.org/z/1q8ascav9。 - ElderBug
@ElderBug 我认为联合体应该具有 __uint128_t 的对齐方式,因为 #pragma pack(1) 仅适用于匿名结构体,而不是整个联合体。 - Ray Hamel
1
如果仅针对内部结构进行打包,则是的。为此,您需要在结构体后添加#pragma pack(0) - ElderBug
显示剩余4条评论

1

你可能会定义

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

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

#define v4 s.v4

我不确定那个宏是一个好主意。

另一种方法是使用你的GCC插件(针对GCC编译器的特定版本)以及由其处理的一些__attribute__


4
在C11或更高版本中,你可以使用匿名结构体成员,并且无需使用宏即可编写ip.v4 - Nate Eldredge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接