可能重复:
转换位字段为int
我工作的一个应用程序,其中一部分的处理包含了许多的1位标志16位字。 我使用类似下面所示的一个结构处理数据:
struct mystruct
{
uint16_t Reserved1 :3;
uint16_t WordErr :1;
uint16_t SyncErr :1;
uint16_t WordCntErr :1;
uint16_t Reserved2 :10;
};
即,结构包含作为多个较小的(在某些情况下,1比特的标记)片处理的单个16位变量中。
我的问题是这样的,有一个简单的方法来处理整个16位字为一个值,比如说,将其输出到控制台或文件,或将其添加到另一个数据结构? 我不知道这样做除了转移的具体的结构元素,并将它们添加到一个临时uint16_t变量的任何方式。 看来,有可能是提取整个字的简单的方法,但我不能找到编译器如何处理的结构是这样的任何信息。
编辑:我想这可能是显而易见的,但我试图简而言之做的是能够单独访问1位标志,以及使用结构类型uint16_t的一个变量(即无符号短,16位)。
这里的标准方法是使用匿名结构/联合,这样的:
union mystruct
{
struct
{
uint16_t Reserved1 :3;
uint16_t WordErr :1;
uint16_t SyncErr :1;
uint16_t WordCntErr :1;
uint16_t Reserved2 :10;
};
uint16_t word_field;
};
或者,如果工会不作为好一个顶级对象,
struct mystruct
{
union
{
struct
{
uint16_t Reserved1 :3;
uint16_t WordErr :1;
uint16_t SyncErr :1;
uint16_t WordCntErr :1;
uint16_t Reserved2 :10;
};
uint16_t word_field;
};
};
该定义允许到内部领域,如直接访问:
mystruct s1;
s1.WordCntErr = 1;
严格地说,编译器不给就如何工会的不同成员将互相重叠的任何担保。 它可以使用不同的路线,甚至转变。 很多人在这里会很容易地指出这一点。 然而,从实用的角度来看看这个,如果工会的各个领域具有相同的大小,你可以安全地假设,他们占据了同一块内存。 例如,代码
s1.word_field = 0;
将归零所有位字段。 代码吨都采用这种。 这是不可想象的,这将不会停止工作。
简单的答案是,你不能做到这一点。 较长的答案是,你可以做到这一点,但在细节上取决于你的编译器。 这种特殊的位字段布局看起来很像它应该映射到硬件寄存器,在这种情况下,你已经有了编译器的依赖关系:对位字段是如何安排的细节是实现定义的。 所以,当你保证自己的编译器勾画出来你所期望的方式,你也可以检查它是否支持通过联合类型的双关语。 虽然写入工会的一个领域,从另一个读正式产生不确定的行为,无论是在C和C ++中,大多数(全部?)编译器都支持它在简单的情况是这样的。
是来自工会技术的未定义行为的替代,你可以复制的数据:
mystruct m;
m.Reserved1 = 0;
m.WordErr = 1;
m.SyncErr = 0;
m.WordCntErr = 0;
m.Reserved2 = 0;
uint16_t value = 0;
memcpy(&value, &m, sizeof(value));
[码]
当然,输出/端敏感的特定于平台的,所以如果你打算写出来,所以你可以读一遍,然后在考虑到这一点。
这是一个什么样的工会是。 我很少需要使用一次,所以我的语法可能会生锈,但是它看起来是这样的:
union myunion
{
struct mystruct
{
uint16_t Reserved1 :3;
uint16_t WordErr :1;
uint16_t SyncErr :1;
uint16_t WordCntErr :1;
uint16_t Reserved2 :10;
};
uint16_t word;
};
当然,这增加了打字,只要你访问它,所以你可能想只是尝试类型转换,如果你只需要偶尔。