第2.18章: endian

English

字节序

字节序描述多字节值在内存中的存储方式:

用 boolalpha 直接打印检查结果:


#include <fast_io.h>
#include <bit>

int main() {
    println("my machine is little endian? ",
          boolalpha(::std::endian::native == ::std::endian::little), "\n"

          "my machine is big endian? ",
          boolalpha(::std::endian::native == ::std::endian::big));
}

使用场景

尽管网络协议和加密方案通常使用大端,如今大多数机器却是小端的。 这意味着在处理网络数据包或加密数据时,系统往往需要来回交换字节。 在具有高效字节交换指令的架构上,这微不足道。 然而,RISC-V 因缺少默认的字节交换指令而受到批评,这会导致碎片化和低效。

::std::byteswap

::std::byteswap 反转整数的字节顺序。 只需打印交换前后的二进制即可:


#include <fast_io.h>
#include <bit>

int main() {
    ::std::uint32_t value{0xDEADBEEFu};

    print("Original value = ", ::fast_io::bin<true,true>(value), "\n");

    value = ::std::byteswap(value);

    print("Byteswapped value = ", ::fast_io::bin<true,true>(value), "\n");
}

例如:0xDEADBEEF 打印为 0b11011110101011011011111011101111。 字节交换之后,它打印为 0b11101111101110101010110111011110。

直观理解 std::byteswap

byteswap 会反转多字节值中各个字节的顺序。 下图展示 0xDEADBEEF 在小端机器内存中的存储方式, 以及 std::byteswap 如何反转字节顺序。

Original (0xDEADBEEF):

Memory bytes (little endian):
┌────┬────┬────┬────┐
│ EF │ BE │ AD │ DE │
└────┴────┴────┴────┘
  ^    ^    ^    ^
  LSB              MSB

After std::byteswap(value):

Memory bytes:
┌────┬────┬────┬────┐
│ DE │ AD │ BE │ EF │
└────┴────┴────┴────┘
  ^              ^
  MSB            LSB
  

数值本身不变,但内存中的字节顺序被反转了。 在小端 CPU 与大端协议(网络数据包、加密格式等)之间转换时,这是必需的。

讨论:RISC-V 与字节序

Linus Torvalds 曾强烈反对为 RISC-V 添加大端支持。 引自 Phoronix 的报道:

"Oh Christ. Is somebody seriously working on BE support in 2025?

WHY?

Seriously, that sounds like just *stupid*. Is there some actual real reason for this, or is it more of the 'RISC-V is used in academic design classes and so people just want to do endianness for academic reasons'?

Because I'd be more than happy to just draw a line in the sand and say 'New endianness problems are somebody ELSES problem', and tell people to stop being silly.

Let's not complicate things for no good reason. And there is *NO* reason to add new endianness.

RISC-V is enough of a mess with the millions of silly configuration issues already. Don't make it even worse.

Tell people to just talk to their therapists instead. That's *much* more productive."

他进一步补充道:

"Ok, I just googled this, and I am putting my foot down:

WE ARE NOT PREEMPTIVELY SUPPORTING BIG-ENDIAN ON RISC-V

The documented 'reasoning' for that craziness is too stupid for words, but since riscv.org did put it in words, I'll just quote those words here:

'There are still applications where the way data is stored matters, such as the protocols that move data across the Internet, which are defined as big-endian. So when a little-endian system needs to inspect or modify a network packet, it has to swap the big-endian values to little-endian and back, a process that can take as many as 10-20 instructions on a RISC-V target which doesn’t implement the Zbb extension'

In other words, it is suggesting that RISC-V add a big-endian mode due to
(a) internet protocols - where byte swapping is not an issue
(b) using 'some RISC-V implementations don't do the existing Zbb extension' as an excuse

This is plain insanity. First off, even if byte swapping was a real cost for networking - it's not, the real costs tend to be all in memory subsystems - just implement the damn Zbb extension.

Don't go 'we're too incompetent to implement Zbb, so we're now asking that EVERYBODY ELSE feel the pain of a much *worse* extension and fragmenting RISC-V further'.

I'm hoping this is some April fools joke, but that page is dated 'March 10, 2025'. Close, but not close enough.

This is the kind of silly stuff that just makes RISC-V look bad.

Ben - I'm afraid that that page has 'further reading' pointing to codethink.

I see some CONFIG_CPU_BIG_ENDIAN has already made it in, but this needs to stop.

The mainline kernel is for mainline development. Not for random experiments that make the world a worse place.

And yes, we're open source, and that very much means that anybody is more than welcome to try to prove me wrong.

If it turns out that BE RISC-V becomes a real thing that is relevant and actually finds a place in the RISC-V ecosystem, then _of_course_ we should support it at that point in the mainline kernel.

But I really do think that it actually makes RISC-V only worse, and that we should *not* actively help the fragmentation."

要点