真实应用中的字节序相关代码?

3

我知道以下的C代码是端序相关的:

short s_endian = 0x4142;
char c_endian = *(char *)&s_endian;

在大端机器上,c_endian的值为'A'(0x41);而在小端机器上,它将是'B'(0x42)。

但这段代码看起来有些丑陋。那么在实际应用中是否存在端序相关的代码呢?或者你是否遇到过需要在不同目标平台上进行端序转换时需要进行大量更改的应用程序?

谢谢。


2
如果所有现实世界的程序员都像你一样理智,那该多好啊... - R.. GitHub STOP HELPING ICE
6个回答

2
几乎所有涉及以二进制格式保存超过8位整数或通过网络发送这些整数的代码都属于此类。一个极为常见的例子是,许多TCP头部中的字段都属于此类。

1

网络编程代码是端序相关的(它应该始终作为大端传输到网络上,即使在小端机器上),因此需要像htons()htonl()ntohs()ntohl()这样的函数,在net/hton.h中允许轻松地进行主机到网络字节序和网络到主机字节序之间的转换。

希望这可以帮助您,

Jason


二进制文件格式保存超过8位的整数需要特殊处理。 - user439793
谢谢。我以前从未进行过网络编程,但传输数据之前将其转换为网络字节顺序不是一个原则吗? - amicaky
是的,在网络传输之前,您应该将数据转换为网络字节顺序,因此需要使用net/hton.harpa/inet.h中提供的转换函数。此外,我更倾向于使用位掩码和移位来获取低/高字节或在大/小端之间进行转换,而不是使用指针强制转换。 - Jason

0

当处理浮点数的内部表示时,您可以使用整数类型访问其部分(或完整值)。例如:

union float_u
{
  float f;
  unsigned short v[2];
};

int get_sign(float f)
{
  union float_u u;
  u.f = f;
  return (u.v[0] & 0x8000) != 0;     // Endian-dependant
}

完全同意。这种代码只适用于特定的格式,例如IEEE-754。 - Lindydancer

0
我曾经在PC上使用专用的DAQ卡收集数据,并尝试在PowerPC Mac上分析文件。结果发现,该设备使用的“文件格式”是原始内存转储...

x86上是小端序,PowerPC上是大端序。你自己想象一下吧。


0
简短的回答是肯定的。任何读/写原始二进制文件或套接字的东西都需要跟踪数据的字节序。
例如,IP协议要求大端表示。

谢谢。我以前从未进行过网络编程,不是将数据转换为网络字节顺序后再传输的原则吗? - amicaky
IP协议规定所有流量必须采用大端表示。这意味着所有接收方都假定您的数据是大端的。如果您不遵守标准,并且您的字节序与接收方不同,那么接收方几乎肯定无法正确解析您的消息。TCP和UDP在IP之上运行,因此这种假设传播到大多数网络协议。 - Oscar Korz

0

如果您的程序将数据发送到另一个系统(通过串行或网络链接,或将其保存到文件中以供其他系统读取),或从另一个系统读取数据,则可能会出现字节序问题。

我不知道静态分析是否能够检测到这种结构,但是让您的程序员遵循编码标准,其中结构元素和变量被标记为指示它们的字节序可能会有所帮助。

例如,如果所有网络数据结构都在多字节成员的名称后附加了_be,则可以查找将非后缀(主机字节顺序)变量或甚至文字值(如0x1234)分配给其中一个成员的实例。

如果我们可以在我们的数据类型中捕获字节序--uint32_be和uint32_le与uint32_t一起使用,那么编译器就可以禁止两者之间的赋值或操作。并且htobe32的签名将是uint32_be htobe32(uint32_t n);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接