【问题标题】:Inconsistent results when dealing with endianness and arrays in C++在 C++ 中处理字节顺序和数组时结果不一致
【发布时间】:2015-04-14 08:59:43
【问题描述】:

我想知道为什么——在我的示例代码中——当将对m_arr 的第一个元素的引用转换为更大大小的指针时,程序会以小端字节顺序将内存读取到m_val?用这种思路*(std::uint8_t*)m_arr应该指向0x38,但它没有。

我的 CPU 使用 little-endian 字节顺序。

#include <iostream>
#include <iomanip>

int main() {
    std::uint8_t m_arr[2] = { 0x5a, 0x38 };

    // explain why m_val is 0x385a and not 0x5a38
    std::uint16_t m_val = *(std::uint16_t*)m_arr;

    std::cout << std::hex << m_val << std::endl;

    return 0;
}

【问题讨论】:

  • 您的代码有未定义的行为。
  • 也就是说,这看起来非常适合 WAI。小端(最不重要的一端)是第一个数组元素。值为a[0] + 0x100 * a[1]。这就是“小端”的意思。
  • 这是小端系统的预期行为,不是吗?最低有效字节(0x5a)在低地址中
  • 这段代码违反了结构别名规则(uint16_t 类型的左值用于访问不同的东西)
  • *(std::uint8_t*)m_arr 不应指向 0x38。您正在获取std::uint8_t 的数组,并执行显式数组到指针的转换。这会给你一个指向第一个元素的指针。字节序在这里无关紧要,因为指针类型与元素的类型相同。

标签: c++ endianness


【解决方案1】:

字节排序是字节在被引用为本机类型时的布局顺序。无论您的机器是大端还是小端,字节序列总是按其自然顺序排列。

如果您创建了uint16_t 并获得了指向它的uint8_t 指针,那么您描述的情况(第一个字节是0x38)就是您将观察到的情况。相反,您有一个 uint8_t 数组,并且您会得到一个 uint16_t 指向它的指针。

【讨论】:

    【解决方案2】:

    Little endian 表示最不重要的字节在前:

    所以将该逻辑转换为您的数组{ 0x5a, 0x38 }。在小端系统上,0x5a 最不重要,0x38 最重要......因此你得到0x385a

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多