c - 跨大型和小型 Endian 机器的数据传输

标签 c char endianness

假设有“cat”、“bat”、“rat”这3个字符串,我需要将它们组合成一个字符串,通过socket编程发送到另一台不同字节序的计算机。

因此,如果另一台机器是大端,我会将字符串打包为:
memcpy (base, "cat", 3)
memcpy (base+3, "bat", 3)
memcpy (base+6, "rat", 3)

如果另一台机器是小端,我会将字符串打包为:
memcpy (base, "rat", 3)
memcpy (base+3, "bat", 3)
memcpy (base+6, "cat", 3)

我的方法对吗?

其次,它们实际上会以相反的顺序在另一台机器上接收吗?我的意思是,当另一台机器的软件开始从“基本”字符串中提取字符串时,它实际上会以相反的顺序排列吗?比如 rat、bat、cat?

最佳答案

当你将一个包含两个字节 0x02 0x00 的内存缓冲区转储到套接字中时,首先发送 0x02,然后发送 0x00发送。当接收器从套接字读取时,0x02 将最先到达,并将存储在缓冲区的开头。 0x00 第二个到达,并紧跟在 0x02 之后存储。因此,在您执行了send(sock, &buffer, 2) 并且接收方执行了recv(sock, &buffer, 2) 之后,您和接收方的 的内容缓冲区是相同的——在字节级别上。

但是现在出现了解释问题。是的,内存中有两个字节 0x02 0x00,但那又怎样?他们的意思是什么?哦,你是说 0..65535 范围内的整数?但是有两种方法可以存储这样的数字。第一种是在第一个字节中存储更多有效位,因此 512 = 10'00000000 存储为 0x02 0x00。第二种是在第一个字节存储低位,所以512存储为0x00 0x020x02 0x00是一种存储方式2,不是 512

因此,重要的教训是:当您发送一些数据时,您必须确保接收方会像您一样解释它们。跨越多个字节的整数可以有不同的解释,因此您必须以某种方式就一种发送它们的方式达成一致。

现在,回到字符串。 C 中的字符串是概念和表示级别上的字节序列——整数不是这样!当您使用整数时,我敢打赌您不会很在意它们被表示为一堆字节,并且实际的表示形式不是由 C 指定的。您的编译器可以以任何它想要的方式存储整数。但是,字符串按特定顺序排列的字节序列,并且在 C 中是固定的。您有第一个字符、第二个字符,依此类推。所以只有一种方法可以将 02 00 解释为字符串:它是一个 2 个字符的字符串,第一个字符为 0x02,第二个字符为 0x00。不可能混淆。

附言当然,当您开始认为字符串不是字节序列,而是 字符 序列时,解释问题又出现了:哪个字节表示什么字符?但那是另一回事了。

编辑:在您对另一个答案的评论中,您说您“必须做出规定让另一台机器知道我发送的实际上是整数而不是字符串”。是的。这是与其他机器交换数据的主要问题:你发送的和他们看到的只是一个字节序列。现在这个交换的所有参与者都必须以相同的方式解释这个字节序列,否则他们会感到困惑。如果你想发送数字 512 并通过发送字节 0x02 0x00 来实现,另一方更好地理解 0x02 0x00 你的意思是 512 而不是 2,或者说 START OF TEXT。或者,当您发送 0x31 0x32 0x33 0x00 时,您指的是 “123”,而不是 82537344031323300

仍然是原始问题的答案:“如果我发送 “catbatrat”,发件人会看到什么?”是:“发件人将看到 “catbatrat”,与字节顺序无关”。

关于c - 跨大型和小型 Endian 机器的数据传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16729496/

相关文章:

c - 将项目移动到数组的前面

更改函数内变量的值

c - libcurl (7.19,7) 在 OSX (10.6.8) 上因 _mdns_query_callback 而崩溃

c++ - 如何读取x86处理器中的中断标志

c++ - 无符号字符串构造不可能

linux - 将十进制数序列转换为大端 float

C - 分配 char 文字与数组文字的行为

c - 在 C 中,我可以将字符串保留为 char*,然后使用指针指向其他字符串吗?

c - 如何根据 "Endianness"以位级别存储数据?

c - 有什么方法可以加速 C 中的 be32 编码吗?