2013-10-21 21 views
21

我想通过一个套接字传递一个32位有符号整数x。为了让接收器知道哪个字节顺序,我在发送之前调用htonl(x)htonl预计会有uint32_t,但我想确定在将我的int32_t投射到uint32_t时会发生什么情况。在signed和unsigned int之间是否保持精确的位模式?

int32_t x = something; 
uint32_t u = (uint32_t) x; 

是否总是在xu每个字节会完全一样的情况下?怎么样铸造回:

uint32_t u = something; 
int32_t x = (int32_t) u; 

我认识到,投大无符号值的负值,但这并不重要,因为我只是铸造回到另一端。但是如果使用实际字节进行强制转换,那么我无法确定强制转换会返回相同的值。

回答

19

一般来说,C中的投射是根据值来指定的,而不是位模式 - 前者将被保留(如果可能的话),但后者不一定如此。如果两个补码表示没有填充 - 这对于固定整数类型是强制性的 - 这个区别并不重要,并且演员确实是一个noop。

但即使从signed到unsigned的转换会改变位模式,将其再次转换回原来的值也会恢复原始值 - 超出范围无符号签名转换的警告是实现定义的,可能会在溢出时发出一个信号。

对于完全的可移植性(这可能会矫枉过正),您需要使用类型双击而不是转换。这可以通过以下两种方式之一进行:

通过指针蒙上,即

uint32_t u = *(uint32_t*)&x; 

,你应该小心,因为它可能违反了有效的打字规则(但罚款整数符号/无符号变种类型)或通过工会,也就是说,如果你想避免不确定的行为

uint32_t u = ((union { int32_t i; uint32_t u; }){ .i = x }).u; 

也可用于例如将从doubleuint64_t,你可能不会做指针强制转换。

+2

不错,+1与工会的解决方案。 –

+0

太棒了,这是我想知道的。因此,它将始终工作提供签名ints使用二进制补码来表示,这几乎总是如此。那是对的吗? – Flash

+1

@Andrew:正确 - 甚至在非二进制补码硬件上,编译器将不得不伪装成固定宽度的整数类型,或者根本不提供它们;在溢出时产生一个信号在实践中也不会成为问题 – Christoph

6

在C语言中使用Casts来表示“类型转换”和“类型消歧”。如果你有类似的东西

(float) 3 

然后它是一个类型转换,实际位改变。如果你说

(float) 3.0 

这是一种消除歧义的类型。

假设2的补码表示(见下文评论),当你施放一个intunsigned int,位模式没有改变,只是它的语义含义;如果你把它放回去,结果总是正确的。它属于类型消歧的情况,因为没有位被改变,只是计算机解释它们的方式。

请注意,理论上,可能不会使用2的补码,并且unsignedsigned可能具有非常不同的表示,实际的位模式可能会在此情况下发生变化。

然而,从C11(当前的C标)时,实际上被保证sizeof(int) == sizeof(unsigned int)

(§6.2.5/ 6)对于每个符号整数类型,有相对应的 (但是,它使用存储相同量的(包括 符号信息)并具有相同的对准要求不同)的无符号整数型(带 关键字无符号指定)[...]

我要说的是在实践中,你可以假设它是安全的。

+1

这是不正确的 - 签名到无符号转换可能会改变位模式 - 它恰好如此,它不会发生在具有相同填充的二进制补码表示 – Christoph

+0

@Christoph好点。我更新了我的答案。 –

+1

现在看起来不错:+1 – Christoph

2

这应该永远是安全的,因为intXX_t类型保证在补如果它们存在:

7.20.1.1精确宽度的整数类型typedef名intN_t指定一个符号整型宽度为N,没有填充位,以及两个补码表示。因此,int8_t表示宽度恰好为8位的有符号整数 。

理论上,该反向转换从uint32_tint32_t被实现定义的,作为所有unsignedsigned转换。但我无法想象一个平台的表现会与你期望的不同。

如果你想真正确定这一点,你仍然可以手动进行转换。你只需要测试> INT32_MAX的值,然后做一些数学运算。即使你有系统地做,一个体面的编译器应该能够检测并优化它。

+0

,我可以设想一个陷阱整数溢出的平台在类型转换时可能会这样做(例如,编译器可能会生成一个无用的“add 0”指令触发它);如果有一个编译器在默认情况下(或者根本就是这样)编译,我会感到非常惊讶;另外,我宁愿选择类型双向比检查“INT32_MAX” - 固定整数不带有陷阱表示,因此就C标准而言,它和安全性一样,并且实际上捕获了前进中的意图 – Christoph

相关问题