C++ 什么时候持久性成为一个因素?
根据我的理解,Endianness是指组成多字节字的字节顺序不同,至少在最典型的情况下是如此。因此,16位整数可以存储为C++ 什么时候持久性成为一个因素?,c++,networking,stl,endianness,C++,Networking,Stl,Endianness,根据我的理解,Endianness是指组成多字节字的字节顺序不同,至少在最典型的情况下是如此。因此,16位整数可以存储为0xhhl或0xLLHH 假设我没有错,我想知道的是,当在两台计算机之间发送信息时,Endian可能不同,也可能不同,Endian何时会成为一个主要因素 如果我发送一个短整数1,以字符数组的形式,并且没有任何更正,它是否被接收并解释为256 如果我使用下面的代码分解并重新组合短整数,endianness将不再是一个因素吗 // Sender: for(n=0, n <
0xhhl
或0xLLHH
假设我没有错,我想知道的是,当在两台计算机之间发送信息时,Endian可能不同,也可能不同,Endian何时会成为一个主要因素
- 如果我发送一个短整数1,以字符数组的形式,并且没有任何更正,它是否被接收并解释为256
- 如果我使用下面的代码分解并重新组合短整数,endianness将不再是一个因素吗
// 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; };
//发送方: 对于(n=0,n
>n)&1; }; //接收人: 对于(n=0,n 值|=uint16(stl_位集[n]&1)端性始终是一个问题。有些人会说,如果你知道连接到网络的每个主机都运行相同的操作系统等,那么你就不会有问题。这是事实,直到它不是。你总是需要发布一个规范,详细说明在线数据的确切格式。它可以是你想要的任何格式,但每个端点都需要了解e格式,并能正确解释 一般来说,协议使用big-endian表示数值,但如果每个人都不兼容IEEE 754等,这会有局限性。如果您可以承担开销,则使用XDR(或您最喜欢的解决方案)并确保安全 - 不,尽管你有正确的总体想法。你缺少的是一个事实,即使它通常是串行连接,网络连接(至少大多数网络连接)仍然保证八位字节(字节)的正确端性级别——也就是说,如果在小端机器上发送一个值为0x12的字节,在大端机器上它仍将作为0x12接收 看一个简短的例子,如果你看十六进制的数字,它可能会有帮助。它以0x0001开头。你把它分成两个字节:0x00 0x01。收到后,它将被读取为0x0100,结果是256
- 由于网络在八位字节级别处理endianess,因此通常只需补偿字节的顺序,而不必补偿字节中的位
- 可能最简单的方法是在发送时使用htons/htonl,在接收时使用ntohs/ntohl。当/如果这还不够时,有许多替代方法,如XDR、ASN.1、CORBA IIOP、Google协议缓冲区等
补偿的“标准方式”是“网络字节顺序”的概念已经被定义,几乎总是(AFAIK)作为big-endian
发送者和接受者都知道有线协议,如果有必要,他们会在发送之前和接收之后进行转换,以便为应用程序提供正确的数据。但这种转换发生在您的网络层内部,而不是应用程序中。请注意,如果您在设备之间传输数据,您几乎应该始终使用n使用
,ntohl
,htonl
,ntohs
进行网络字节排序。无论您的系统和目标系统使用什么,它都将转换为网络字节顺序标准,以实现端性。当然,这两个系统都应该这样编程-但它们通常在网络场景中。非常有用简而言之,endianness是将变量重新解释为字符数组的属性 实际上,当您从外部字节流(如文件或套接字)读取()和写入()时,这一点非常重要。或者,抽象地说,当您序列化数据时,endianness非常重要(本质上是因为序列化数据没有类型系统,只由哑字节组成);而endianness在您的编程语言中并不重要,因为该语言只对值进行操作,而不对表示进行操作。从一个到另一个是您需要深入了解细节的地方 也就是说,写作:htons
在这里,我们可以说,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);
,结果将取决于系统的持久性 并阅读:重新解释cast(&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
unsigned char buf[4]=read_data();
uint32_t n_LE=buf[0]+buf[1]你不必担心,除非你在系统的边界。通常,如果你在谈论stl,你已经通过了边界 序列化协议的任务是指示/确定如何将一系列字节转换为要发送的类型,即内置类型或自定义类型
如果你说的是内置的,那么你可能已经满足了[C/C++endian中性代码的机器抽象要求。这里有一些C/C++endian中性代码的指导原则。显然,这些都是作为“避免的规则”编写的……因此,如果代码有这些“特性”,它可能容易出现与endian相关的错误!!(这是我在Dobbs博士上发表的关于Endianness的文章)- 避免使用组合不同多字节数据类型的联合。 (活接头的布局可能具有不同的endian相关顺序)
- 避免访问字节数据类型之外的字节数组。 (字节数组的顺序具有与endian相关的顺序)
- 避免使用位字段和字节掩码 (由于存储器的布局取决于尾数,字节的屏蔽和位字段的选择是尾数敏感的)
- 避免将指针从多字节类型转换为其他字节类型。
(指针从一种类型转换为另一种类型时,源(即原始目标)的终止性将丢失,后续处理可能不正确)
据我所知,这两种终端都有一个优势:- Big-endian在概念上更容易理解,因为它类似于我们的位置数字系统:从最重要到最不重要
- 在重用内存时,Little endian非常方便