C++ uint12结构中的Endianness

C++ uint12结构中的Endianness,c++,struct,endianness,unions,C++,Struct,Endianness,Unions,假设我有如下数据: union { struct { char flags : 4; uint16_t : 12; } char data[2]; } 我了解如何在平台上运行此代码,而不考虑字节的长度。我要求确保我对如何将其存储在不同的Endian上的理解是正确的 据我了解: 如果我将uint16存储在12位uint中,两个Endian都会删除最高的4位。Big-endian将剩余的4个高位存储在与标志相同的字节中,其余高位存储在单独的字节中。Little

假设我有如下数据:

union
{
  struct
  {
    char flags : 4;
    uint16_t   : 12;
  }
  char data[2];
}
我了解如何在平台上运行此代码,而不考虑字节的长度。我要求确保我对如何将其存储在不同的Endian上的理解是正确的

据我了解: 如果我将uint16存储在12位uint中,两个Endian都会删除最高的4位。Big-endian将剩余的4个高位存储在与标志相同的字节中,其余高位存储在单独的字节中。Little endian将4个最低位存储在与标志相同的字节中,其余位存储在单独的字节中


这是否正确?

这取决于编译器和目标平台的ABI。例如,参见以下规则:单元内位字段的分配顺序由ABI确定。此外,每个字段都应该声明为
int
unsigned int
,而不是
uint16\u t

如果要控制数据格式,可以使用移位和掩蔽将数据组合成
uint16\t
。如果您的目标是以定义良好的格式写入数据,则可以按要求的尾数写入
uint16\u t
字节,或者只需将数据组合成2个字节,然后按要求的顺序写入


除非你发现语言规范文档承诺了你想要的,或者你的编译器文档明确承诺了,并且你对大小端的CPU使用相同的编译器,否则不要依赖C/C++编译器以同样的方式完成类似的工作。

C++规范试图定义并提供逻辑正确的语言,不是一种对比特正确的语言;如果这对你有意义的话。换句话说,
C++
既不关心也不指定位级别上使用的信息的表示,这与无法将
float
推断为模板参数的原因类似,
C++
没有提供表示
float
的定义,因此它甚至不能提供模板所必需的一些基本保证。这一切都是特定于编译器和ABI的。所以这不仅取决于平台,还取决于您使用的编译器?现在回想一下,我记得
uint16\u t
不是定义为基类型,而是在单独的头中声明的。位字段应该只支持基类型,这是有道理的。我最初的希望是,我可以在每条消息中包含一个“endianness”字段,如果主机的endianness与消息的发送方的endianness相同,那么我可以跳过位移位,并将原始数据加载到如上所述的联合中。我知道这不起作用。字段之间的填充也可能因编译器和目标平台而异。通常的方法是始终以“网络字节顺序”(即big-endian)发送数据。有关示例标准,请参见XDR。有一些图书馆可以帮助您完成这项工作。谢谢您的帮助。我知道如何使这个endian不可知,我只是在寻找微小的优化-出于个人兴趣。我不可能根据如此挑剔的东西来编写代码。显然,对于字节大小的数据,填充几乎总是不存在的。“提高你的回答,因为你帮了大忙。很高兴能帮上忙,”安德鲁说