将32位大端符号整数转换为带符号的小端整数

时间:2018-05-10 18:14:10

标签: c++ bit-manipulation endianness

我需要转换一些无符号的32位大端整数,一旦找到正确的标题,这很简单:

#include <endian.h>
...
be32toh(some_int);

但是,endian.h指定这些是无符号整数。对于有符号整数,我不确定该怎么做,因为它看起来不像这种东西的头文件,而且我不熟悉C ++中的位操作。

编辑:由于我的整数格式存在一些混淆,让我解释一下。我有一个

形式的整数
abcdefghijklmnopqrstuvwxyz012345

其中每个字符代表一点。 a位表示符号。我知道字节总是大端,所以除了将字节移动到不同的顺序,比如

yz012345qrstwx...

我还需要一些方法来确保y位显示符号,而不仅仅是数字中的一些位。我......不知道该怎么做。

编辑:我的问题是我认为符号位总是先排序,但事实并非如此。符号位始终是MSB,这意味着如果您处于小端形式,则符号位将位于构成整数的字节的中间。

2 个答案:

答案 0 :(得分:2)

尝试对带符号的整数进行字节反转听起来并不像是一个明确定义的算术运算,因为最高有效位表现为整数符号的指示,并且它不会在操纵整数变量时将它移到别处是很有意义的。

更有可能的是,您可能有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 整数意味着什么的问题在数学上并不明确。

答案 1 :(得分:2)

这只有在原生系统是小端的情况下才有意义,因为在大端系统上将数据转换为带符号的little-endian会是什么意思?

因此在小端系统上,您需要做的就是将big-endian整数转换为unsigned,使用be32toh转换它,然后将结果转换为有符号整数。实际上,最好将big-endian从一开始就表示为无符号,因为它的符号在小端系统中没有任何意义。因此,只需转换无符号位,然后转换为signed。