Fla*_*ash 27 c int unsigned casting htonl
我想x通过套接字传递一个32位有符号整数.为了让接收器知道预期的字节顺序,我htonl(x)在发送之前调用.htonl期待一个,uint32_t但我想确定当我把我int32_t带到一个时会发生什么uint32_t.
int32_t x = something;
uint32_t u = (uint32_t) x;
Run Code Online (Sandbox Code Playgroud)
总是这样的情况,每个字节x和u每个字节都完全相同吗?怎么回事:
uint32_t u = something;
int32_t x = (int32_t) u;
Run Code Online (Sandbox Code Playgroud)
我意识到负值会转换为大的无符号值,但这并不重要,因为我只是回到了另一端.但是,如果使用实际字节进行混乱,那么我无法确定返回将返回相同的值.
Chr*_*oph 26
通常,C中的转换是根据值而不是位模式指定的 - 前者将被保留(如果可能),但后者不一定如此.如果没有填充的二进制补码表示 - 这对于固定的整数类型是强制性的 - 这种区别无关紧要,并且强制转换确实是一个noop.
但即使从有符号到无符号的转换会改变位模式,再次将其转换回来也会恢复原始值 - 需要注意的是超出范围的无符号到有符号转换是实现定义的,并且可能会引发信号溢出.
为了完全可移植性(这可能是过度杀伤),您需要使用类型惩罚而不是转换.这可以通过以下两种方式之一完成:
通过指针转换,即
uint32_t u = *(uint32_t*)&x;
Run Code Online (Sandbox Code Playgroud)
你应该小心,因为它可能违反有效的打字规则(但对整数类型的有符号/无符号变体是好的)或通过工会,即
uint32_t u = ((union { int32_t i; uint32_t u; }){ .i = x }).u;
Run Code Online (Sandbox Code Playgroud)
如果你想避免未定义的行为,它也可以用于转换double为uint64_t,如果你不想使用指针转换.
在C中使用强制转换表示"类型转换"和"类型消歧".如果你有类似的东西
(float) 3
Run Code Online (Sandbox Code Playgroud)
然后是类型转换,实际位改变.如果你说
(float) 3.0
Run Code Online (Sandbox Code Playgroud)
这是一种消除歧义的类型.
假设2的补码表示(见下面的评论),当你施放一个int到unsigned int,该位模式没有改变,只是它的语义含义; 如果你把它丢回来,结果总是正确的.它属于类型消歧的情况,因为没有位被更改,只有计算机解释它们的方式.
注意,理论上,可以不使用2的补码,unsigned并且signed可以具有非常不同的表示,并且在这种情况下实际的位模式可以改变.
但是,从C11(当前的C标准),您实际上可以保证sizeof(int) == sizeof(unsigned int):
(§6.2.5/ 6)对于每个有符号整数类型,有一个相应的(但不同的)无符号整数类型(用关键字unsigned指定),它使用相同数量的存储(包括符号信息)并具有相同的对准要求[...]
我会说在实践中,你可以认为它是安全的.
| 归档时间: |
|
| 查看次数: |
23373 次 |
| 最近记录: |