【发布时间】:2015-05-28 08:28:03
【问题描述】:
我正在尝试构建自己的库,用于在不同字节序的整数和有符号表示之间进行转换。其中一部分涉及直接访问 char 缓冲区作为相同大小的整数(主要用于快速比较)。我非常担心这个项目的可移植性。  我希望这个库可以在所有机器和新旧 c 编译器上使用,而不仅仅是 gcc 或 linux 上的 clang。
最初我对整数成员使用 c99 固定宽度整数类型。  这很好用。  当我从固定宽度整数切换到相同大小的位字段时,问题就开始了。我这样做是为了通过不依赖 c99 功能来提高可移植性。 
问题是,当我使用位字段时,gcc 抱怨已插入填充(-Werror 和 -Wpadded 已传递给 gcc):
错误:将结构大小填充到对齐边界
以下是其中一个联合的示例:
旧版本,运行良好:
typedef union
{
unsigned char bytes[4];
uint32_t uvalue;
} upicl_uint32_be;
新版本,添加了不需要的填充:
typedef union
{
unsigned char bytes[4];
unsigned long uvalue : 32;
} upicl_uint32_be;
我不知道为什么当 32 位位字段已对齐时,为什么要向联合中添加填充。
有没有更好的方法来做到这一点?
【问题讨论】:
-
在这种情况下,更好的方法是
memcpy。老实说,如果使用 C 编译器对任何东西的可移植性是一个问题,那么如果担心你将不得不放弃位域作为一个失败的原因。如果你不走运,你的编译器可能不支持长位域。如果您真的不走运,它甚至可能没有 8 位字符。哦,你确定你的 C 编译器没有 >32 位长吗? -
我的代码检查以确保 CHAR_BIT == 8 并且除非这是真的,否则不会编译。
-
那么你已经放弃支持所有编译器了吗? ;)
-
抱歉造成误会。我指的是绝大多数编译器(在具有 8 位字符的普通系统上)。
-
Zeb Thompson:抱歉,我不是故意轻视您在确保便携性方面所做的努力。我的意思是在完全符合标准的 C 中做任何实际工作本质上是在浪费时间(想想 C89 中外部标识符中的 6 个重要字符)。正如您似乎正在做的那样,诀窍是选择一个适合您的应用程序的合理子集,并希望您做出了明智的选择。
标签: c padding unions bit-fields