uint8_t同一二进制文件的不同十进制值

时间:2018-10-10 09:55:28

标签: c++

我使用运行mbedOS 5.9的ARM®Cortex™-M4F CPU遇到以下问题。

假设我具有二进制值10101000,并且我还具有以下union / struct:

union InputWord_u
    {
        uint8_t all;

        struct BitField_s
        {
            uint8_t start   : 1; // D7
            uint8_t select  : 3; // D6, D5, D4
            uint8_t payload : 4; // D3, D2, D1, D0
        } bits;
    };

我有一个简单的程序,可以访问我的单词并按以下方式分配值:

InputWord_u word;
word.bits.start = 0b1;
word.bits.select = 0b010;
word.bits.payload = 0b1000;

因此,word.all == 10101000uint8_t

如果我这样打印printf("%u", word.all);,那么我会收到133的值。

如果我再定义以下uint8_t

uint8_t value = 0b10101000;

并使用printf("%u", value);打印,然后我收到值168

我希望两个值都等于168。

我很欣赏这很可能是我严重误解了Struct在内存中的表示方式。但是,有人可以解释到底发生了什么吗?

谢谢。

3 个答案:

答案 0 :(得分:4)

该标准几乎不能保证位域的表示。

  

因此,word.all == 10101000

您在这里遇到的问题是,您假设位字段是从最高有效位到最低有效位打包的。

但是,看来您的位字段是以相反的顺序存储的,实际上是word.all == 1000'010'1。为了获得您期望的结果,您可以对位字段重新排序:

struct BitField_s
{
    uint8_t payload : 4; // D3, D2, D1, D0
    uint8_t select  : 3; // D6, D5, D4
    uint8_t start   : 1; // D7
} bits;

但是请注意,位错不可移植:其他系统可能没有相同的顺序。

答案 1 :(得分:3)

问题是,您以相反的方式计算值,例如

(start << 7) | (select << 4) | payload

实际值的计算类似于

(payload << 4) | (select << 1) | start

因此,您的位字段以uint8的次要部分开头。它与系统的低端顺序无关,因为低端顺序定义了uint16uint32等字节的字节顺序。

字节内位域的位顺序由编译器定义。例如,如您的示例中的MSVC uses low-to-high order

答案 2 :(得分:2)

二进制值133和168

133 = 10000101
168 = 10101000

假定实际对齐方式与您假定的对齐方式不同。

似乎是按以下方式安排的:

----     ---     -
         all
payload  select  start

您假设以下顺序

-     ---  ----
start all  payload

我还认为不同的编译器具有不同的对齐方式。