【问题标题】:Separating 2 byte number into two 1 bytes将 2 字节数分成两个 1 字节
【发布时间】:2019-07-19 07:04:45
【问题描述】:

我试图将一个 2 字节的数字分成两个 1 字节的数字。但我得到错误的结果。假设号码为:0x1234H

uint8_t high = 0;
uint8_t low = 0;

high = static_cast<uint8_t >(val & 0xFF);
low = static_cast<uint8_t >(val >> 8);

cout << std::bitset<8>(high) << endl;
cout << std::bitset<8>(low) << endl;

cout << "high byte: " << static_cast<int >(high) << endl;
cout << "low byte: " << static_cast<int >(low) << endl;

当我运行代码时,我希望得到以下输出:

0x1234
00001100
00010010
high byte: 12
low byte: 34

然而我得到了,

0x1234
00110100
00010010
high byte: 34
low byte: 12

为什么我的尝试失败了?

【问题讨论】:

  • val &amp; 0xFF 给你的是低字节,而不是高字节
  • val &gt;&gt; 8 为您提供高字节(iff val 是一个 16 位整数,否则您可能需要屏蔽更多高位)。
  • 在英语中,当一个数字被 cout'd(显示或打印)给用户时,最低有效字节总是在 text-representing-the-number 的右端(无论主机字节序)。因此,0x1234 是数字的文本,34 是最低有效 8 位。
  • 请展示一个完整的例子,混淆十六进制/十进制文字和输出是相当普遍的,所以即使你做对了,添加缺失的部分会使问题更清楚
  • ...例如,打印0x34 不会在您的屏幕上显示34(除非您使用正确的io-manipulator)

标签: c++ binary bit-manipulation bit-shift


【解决方案1】:

那是因为您在这些行中错误地命名了变量...

high = static_cast<uint8_t >(val & 0xFF);
low = static_cast<uint8_t >(val >> 8);

&gt;&gt; 运算符将位从高位位置向下移动到低位位置。如果您必须将这些位向下移动以保留它们(在演员​​表中),那是因为它们最初不是低位。所以...

low = static_cast<uint8_t >(val & 0xFF);
high = static_cast<uint8_t >(val >> 8);

顺便说一句 - 当您转换为 uint8_t 时,按位和运算符是多余的 - 这已经足以丢弃除低字节之外的所有内容。它仍然是正确的,只是没有必要。

【讨论】:

  • 当您转换为 uint8_t 时,按位和运算符是多余的——不管机器的字节顺序如何,它总是正确的吗?
  • @snr - 是的,static_cast 不存在字节序问题。受字节序影响的方式是,如果您将reinterpret_cast 从一个大整数转换为一个较小整数的数组,因为字节序会影响较大整数的哪一位与内存布局中的哪个较小整数相关,但@987654326 @ 处理值,而不是布局。结果仍然是平台定义的,但仅限于特定整数类型的位数可能会有所不同 - 比reinterpret_cast(或涉及union的类似技巧)更严格的限制。
  • @snr - 对于按位运算和static_cast,低位始终是最低有效位,如果将它们存储在内存中,它们的排列方式是一个不同的问题。有一些基于此处理二进制文件格式的建议-您担心文件格式中的字节序,并基于此进行提取和写入/读取和重新组装,而无需关心您的代码平台使用的字节序约定正在运行。与使用 unionreinterpret_cast 的技巧相比,代码更易于移植,您需要担心 两个 字节序约定。
猜你喜欢
  • 1970-01-01
  • 2013-04-19
  • 1970-01-01
  • 2021-03-24
  • 2021-10-08
  • 2016-09-02
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
相关资源
最近更新 更多