根据我的理解,字节顺序是组成多字节字的字节顺序不同,至少在最典型的情况下。这样一个16位整数可以存储为0xHHLL
或0xLLHH
。
假设我没有那么错,我想知道的是,当Endian可能会或可能没有不同的两台计算机之间发送信息时,Endianness何时成为主要因素。
如果我以char数组的形式传输1的短整数且没有校正,是否收到并解释为256?
如果我使用以下代码分解并重新组合短整数,那么字节序不再是一个因素吗?
// Sender:
for(n=0, n < sizeof(uint16)*8; ++n) {
stl_bitset[n] = (value >> n) & 1;
};
// Receiver:
for(n=0, n < sizeof(uint16)*8; ++n) {
value |= uint16(stl_bitset[n] & 1) << n;
};
提前致谢!
答案 0 :(得分:50)
非常抽象地说,字节序是将变量重新解释为char数组的属性。
实际上,当你从read()
和write()
到外部字节流(如文件或套接字)时,这很正确。或者,再次抽象地说,当你序列化数据时,字节序很重要(主要是因为序列化数据没有类型系统,只是由哑字节组成);和endianness 从一个到另一个是您需要深入细节的地方。
即做 - 写作:
uint32_t n = get_number();
unsigned char bytesLE[4] = { n, n >> 8, n >> 16, n >> 24 }; // little-endian order
unsigned char bytesBE[4] = { n >> 24, n >> 16, n >> 8, n }; // big-endian order
write(bytes..., 4);
我们可以说,reinterpret_cast<unsigned char *>(&n)
,结果将取决于系统的字节顺序。
阅读:
unsigned char buf[4] = read_data();
uint32_t n_LE = buf[0] + buf[1] << 8 + buf[2] << 16 + buf[3] << 24; // little-endian
uint32_t n_BE = buf[3] + buf[2] << 8 + buf[1] << 16 + buf[0] << 24; // big-endian
同样,在这里我们可以说uint32_t n = *reinterpret_cast<uint32_t*>(buf)
,结果将取决于机器的字节顺序。
正如您所看到的,如果使用代数输入和输出操作,使用整数类型,您永远不必知道自己系统的字节序,只知道数据流的字节序。对于其他数据类型,例如double
,问题就更复杂了。
答案 1 :(得分:35)
对于记录,如果您在设备之间传输数据,则几乎总是使用ntohl
,htonl
,ntohs
,htons
的网络字节顺序。无论您的系统和目标系统使用什么,它都将转换为Endianness的网络字节顺序标准。当然,这两个系统都应该像这样编程 - 但它们通常都在网络场景中。
答案 2 :(得分:7)
不,虽然你确实有正确的总体想法。你所缺少的是这样的事实,即使它通常是串行连接,网络连接(至少大多数网络连接)仍然保证八位字节(字节)级别的正确字节顺序 - 即,如果你发送一个带有值的字节在小端机器上的0x12,在大端机器上它仍然会被接收为0x12。
看一下,如果你看一下十六进制的数字,它可能会有所帮助。它从0x0001开始。你将它分成两个字节:0x00 0x01。收到后,将被读为0x0100,结果为256.
由于网络处理八位字节级别的字节顺序,通常只需要补偿字节顺序,而不是字节内的位。
可能最简单的方法是在发送时使用htons / htonl,在接收时使用ntohs / ntohl。当/如果这还不够时,有许多替代方案,如XDR,ASN.1,CORBA IIOP,Google协议缓冲区等。
答案 3 :(得分:6)
补偿的“标准方式”是“网络字节顺序”的概念已被定义,几乎总是(AFAIK)作为大端。
发送者和接收者都知道有线协议,如果需要,将在发送之前和接收之后进行转换,以便为应用程序提供正确的数据。但是,此转换发生在网络层内部,而不是在您的应用程序中。
答案 4 :(得分:6)
这两个结尾都有我所知道的优势:
unsigned int*
的指针,但你知道存储的值是&lt; 256,您可以将指针投射到unsigned char*
。答案 5 :(得分:5)
一般来说,协议使用big-endian来表示数值,但如果每个人都不兼容IEEE 754等,这就有局限性。如果你可以节省开销,那么使用XDR(或你最喜欢的解决方案)并保证安全
答案 6 :(得分:4)
以下是一些C / C ++ endian-neutral代码的指南。显然这些被写成“要避免的规则”......所以如果代码具有这些“功能”,它可能容易出现与字节序相关的错误! (这是我在Dobbs博士上发表的关于Endianness的文章)
避免使用组合了不同多字节数据类型的联合。 (工会的布局可能有不同的与端相关的订单)
避免访问byte数据类型之外的字节数组。 (字节数组的顺序具有与字节序相关的顺序)
避免使用位字段和字节掩码 (由于存储的布局取决于字节顺序,字节的掩码和位字段的选择是字节序敏感的)
避免将指针从多字节类型转换为其他字节类型 (当指针从一种类型转换为另一种类型时,源的字节顺序(即原始目标)将丢失,后续处理可能不正确)
答案 7 :(得分:3)
除非你在系统的边界,否则你不必担心。通常,如果您正在谈论stl,那么您已经通过了该边界。
序列化协议的任务是指示/确定如何将一系列字节转换为您正在发送的类型,内置类型或自定义类型。
如果你只是内置说话,你可以满足tools provided by your environment提供的机器抽象