我有一些需要转换的无符号 32 位大端整数,一旦找到正确的标头,这就变得非常简单:
#include <endian.h>
...
be32toh(some_int);
但是,
endian.h
指定这些是无符号整数。对于有符号整数,我不太确定该怎么做,因为看起来没有此类事情的头文件,而且我不太熟悉 C++ 中的位操作。
编辑:由于我的整数格式有些混乱,让我解释一下。我有一个以下形式的整数
abcdefghijklmnopqrstuvwxyz012345
其中每个字符代表一个位。
a
位代表符号。我知道字节始终是大端字节序,因此除了将字节移动到不同的顺序之外,例如
yz012345qrstwx...
我还需要某种方法来确保
y
位显示符号,而不仅仅是数字中的某些位。我...不知道该怎么做。
编辑:我的问题是我认为符号位总是按顺序排在第一位,但事实并非如此。符号位始终是 MSB,这意味着如果您采用小端形式,则符号位将位于组成整数的字节的中间。
尝试对一个signed整数进行字节反转听起来不像是一个定义明确的算术运算,因为最高有效位充当整数符号的指示符,并且移动没有多大意义在其他地方操作整数变量时。
更有可能的是,您可能有 4 个字节的序列,表示 32 位有符号整数,但需要进行字节反转以便在不同的 CPU 字节序之间进行转换。为此,您可以简单地将数量视为未签名,然后让
be32toh()
为您完成工作:
(int)be32toh((unsigned)some_int);
或者,稍微安全一点:
(int32_t)be32toh((uint32_t)some_int);
这是有效的,因为当转换操作应用于相同位深度的整数时,有效地使内存中的表示保持不变。在进行字节反转时,这忽略了符号的重要性(以及与有符号整数的二进制补码表示相关的任何微妙之处)。我不确定 C 标准是否保证这种行为(也许是语言律师的问题),但这可能是一种非常常见的行为。 www.cplusplus.com 中的描述表明,如果您的系统使用二进制补码表示其有符号整数(这很常见),那么
(uint32_t)some_int
中的有符号到无符号转换将执行正确的操作。然而,(int32_t)be32toh(...)
中有符号到无符号转换的精确解释严格地依赖于实现。因此,我再次认为对 signed 整数进行字节反转意味着什么的问题在数学上并不是明确的。
只有当本机系统是小端系统时,这才有意义,因为在大端系统上将数据转换为带符号的小端系统有什么意义?
因此,在小端系统上,您所需要做的就是将大端整数转换为无符号整数,使用
be32toh
进行转换,然后将结果转换为有符号整数。实际上,最好从一开始就将大端表示为无符号,因为它的符号在小端系统中没有任何意义。因此,只需转换无符号位,然后转换为有符号位即可。