如何将signed int转换为15位的bit-field?

时间:2016-03-17 15:56:45

标签: c bit-fields

我有一些位域:

int somefield : 15;

我试图将int转换为15位(可以是正数或负数)。

有效地完成这项工作的最佳做​​法是什么?

2 个答案:

答案 0 :(得分:4)

  

我正在尝试将int转换为15位(可以是正数或负数)。有效地做到这一点的最佳做法是什么?

如果要转换的int在15位有符号整数的范围内,请使用以下代码。重要的是不要在没有int的情况下使用signed来定义位域,因为这是C规范中的一个位置,它会有所不同。如果没有signedint位字段可以实现为unsigned。它是实现定义。

signed int somefield:15;
...
x.somefield = 12345;
int y = x.somefield;

如果要转换的int可能超出15位有符号整数的范围,最好使用unsigned字段来实现可移植的一致定义行为。目前还不清楚当int超出范围时OP想要存储的价值。如果需要恢复标志,则可能需要一些额外的代码。根据编码需要,写入时不会产生额外开销,也可能导致读取开销。

unsigned somefield:15;
...
x.somefield = 123456;

x.somefield = -1;
int y = x.somefield >= 0x4000 ? x.somefield - 0x8000 : x.somefield;

或者,如果要分配的值可能在位域范围之外,则确保不会发生分配。写入时的额外开销,读取时没有。

signed int somefield 15;
...
if (i >= INT15_MIN && i <= INT15_MAX) x.somefield = i;
else TBD();

int y = x.somefield;

答案 1 :(得分:0)

chux,非常感谢! 我找到了另一种选择,它看起来也很简单:

typedef struct {
    unsigned int firstletter: 5;
    unsigned int secondletter: 5;
    unsigned int thirdletter: 5;
  } data_in_32_format;

typedef struct {
    unsigned int somedata: 15;
  } data;

typedef union {
    data_in_32_format;
    data;
  } common_data;

所以,当我自己编写数据时,我正在写:

common_data entry;
entry.data = getint_in_decimal_format;

比我用32格式打印:

print32("%c%c%c\n", entry.data_in_32_format.thirdletter
                  , entry.data_in_32_format.secondletter
                  , entry.data_in_32_format.firstletter);

原因我需要在之前正确地将它转换为char(0-9 =&gt;数字,&gt; 9 - 字母,所以在ASCII中需要+55才能正确表示32位格式(A代表10)等等。)。